Merge "Separate android.test.mock classes from android.test.runner"
diff --git a/api/current.txt b/api/current.txt
index dc1d38b..37cb728 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -38684,14 +38684,18 @@
 
   public final class StructStat {
     ctor public StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
+    ctor public StructStat(long, long, int, long, int, int, long, long, android.system.StructTimespec, android.system.StructTimespec, android.system.StructTimespec, long, long);
+    field public final android.system.StructTimespec st_atim;
     field public final long st_atime;
     field public final long st_blksize;
     field public final long st_blocks;
+    field public final android.system.StructTimespec st_ctim;
     field public final long st_ctime;
     field public final long st_dev;
     field public final int st_gid;
     field public final long st_ino;
     field public final int st_mode;
+    field public final android.system.StructTimespec st_mtim;
     field public final long st_mtime;
     field public final long st_nlink;
     field public final long st_rdev;
@@ -38714,6 +38718,13 @@
     field public final long f_namemax;
   }
 
+  public final class StructTimespec implements java.lang.Comparable {
+    ctor public StructTimespec(long, long);
+    method public int compareTo(android.system.StructTimespec);
+    field public final long tv_nsec;
+    field public final long tv_sec;
+  }
+
   public final class StructUtsname {
     ctor public StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     field public final java.lang.String machine;
@@ -49069,7 +49080,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
-    method public static void setSafeBrowsingWhiteList(java.util.List<java.lang.String>);
+    method public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index 22e4c1f..ca34142 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -267,6 +267,14 @@
 
 }
 
+package android.net.wifi {
+
+  public class WifiManager {
+    method public deprecated boolean setWifiApEnabled(android.net.wifi.WifiConfiguration, boolean);
+  }
+
+}
+
 package android.os {
 
   public class BatteryManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9e2b87d..678a4cd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -191,6 +191,8 @@
     field public static final java.lang.String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
     field public static final java.lang.String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
     field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
+    field public static final java.lang.String READ_PRINT_SERVICES = "android.permission.READ_PRINT_SERVICES";
+    field public static final java.lang.String READ_PRINT_SERVICE_RECOMMENDATIONS = "android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS";
     field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
     field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
     field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
@@ -29184,7 +29186,7 @@
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
-    method public boolean setWifiApEnabled(android.net.wifi.WifiConfiguration, boolean);
+    method public deprecated boolean setWifiApEnabled(android.net.wifi.WifiConfiguration, boolean);
     method public boolean setWifiEnabled(boolean);
     method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler);
     method public deprecated boolean startLocationRestrictedScan(android.os.WorkSource);
@@ -38564,6 +38566,22 @@
     field public static final java.lang.String TYPE = "type";
   }
 
+  public final class TimeZoneRulesDataContract {
+    field public static final java.lang.String AUTHORITY = "com.android.timezone";
+  }
+
+  public static final class TimeZoneRulesDataContract.Operation {
+    field public static final java.lang.String COLUMN_DISTRO_MAJOR_VERSION = "distro_major_version";
+    field public static final java.lang.String COLUMN_DISTRO_MINOR_VERSION = "distro_minor_version";
+    field public static final java.lang.String COLUMN_REVISION = "revision";
+    field public static final java.lang.String COLUMN_RULES_VERSION = "rules_version";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String TYPE_INSTALL = "INSTALL";
+    field public static final java.lang.String TYPE_NO_OP = "NOOP";
+    field public static final java.lang.String TYPE_UNINSTALL = "UNINSTALL";
+  }
+
   public class UserDictionary {
     ctor public UserDictionary();
     field public static final java.lang.String AUTHORITY = "user_dictionary";
@@ -41925,14 +41943,18 @@
 
   public final class StructStat {
     ctor public StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
+    ctor public StructStat(long, long, int, long, int, int, long, long, android.system.StructTimespec, android.system.StructTimespec, android.system.StructTimespec, long, long);
+    field public final android.system.StructTimespec st_atim;
     field public final long st_atime;
     field public final long st_blksize;
     field public final long st_blocks;
+    field public final android.system.StructTimespec st_ctim;
     field public final long st_ctime;
     field public final long st_dev;
     field public final int st_gid;
     field public final long st_ino;
     field public final int st_mode;
+    field public final android.system.StructTimespec st_mtim;
     field public final long st_mtime;
     field public final long st_nlink;
     field public final long st_rdev;
@@ -41955,6 +41977,13 @@
     field public final long f_namemax;
   }
 
+  public final class StructTimespec implements java.lang.Comparable {
+    ctor public StructTimespec(long, long);
+    method public int compareTo(android.system.StructTimespec);
+    field public final long tv_nsec;
+    field public final long tv_sec;
+  }
+
   public final class StructUtsname {
     ctor public StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     field public final java.lang.String machine;
@@ -52737,7 +52766,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
-    method public static void setSafeBrowsingWhiteList(java.util.List<java.lang.String>);
+    method public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
@@ -52939,7 +52968,7 @@
     method public abstract java.lang.String getDefaultUserAgent(android.content.Context);
     method public abstract void initSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>);
     method public abstract android.net.Uri[] parseFileChooserResult(int, android.content.Intent);
-    method public abstract void setSafeBrowsingWhiteList(java.util.List<java.lang.String>);
+    method public abstract void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
     method public abstract void setWebContentsDebuggingEnabled(boolean);
     method public abstract void shutdownSafeBrowsing();
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index cd6637f..b9f9be5d2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -32733,9 +32733,7 @@
 
   public final class PrintManager {
     method public java.util.List<android.print.PrintJob> getPrintJobs();
-    method public java.util.List<android.printservice.PrintServiceInfo> getPrintServices(int);
     method public android.print.PrintJob print(java.lang.String, android.print.PrintDocumentAdapter, android.print.PrintAttributes);
-    field public static final int ALL_SERVICES = 3; // 0x3
   }
 
   public final class PrinterCapabilitiesInfo implements android.os.Parcelable {
@@ -32865,13 +32863,6 @@
     field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
   }
 
-  public final class PrintServiceInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.content.ComponentName getComponentName();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.printservice.PrintServiceInfo> CREATOR;
-  }
-
   public abstract class PrinterDiscoverySession {
     ctor public PrinterDiscoverySession();
     method public final void addPrinters(java.util.List<android.print.PrinterInfo>);
@@ -38903,14 +38894,18 @@
 
   public final class StructStat {
     ctor public StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
+    ctor public StructStat(long, long, int, long, int, int, long, long, android.system.StructTimespec, android.system.StructTimespec, android.system.StructTimespec, long, long);
+    field public final android.system.StructTimespec st_atim;
     field public final long st_atime;
     field public final long st_blksize;
     field public final long st_blocks;
+    field public final android.system.StructTimespec st_ctim;
     field public final long st_ctime;
     field public final long st_dev;
     field public final int st_gid;
     field public final long st_ino;
     field public final int st_mode;
+    field public final android.system.StructTimespec st_mtim;
     field public final long st_mtime;
     field public final long st_nlink;
     field public final long st_rdev;
@@ -38933,6 +38928,13 @@
     field public final long f_namemax;
   }
 
+  public final class StructTimespec implements java.lang.Comparable {
+    ctor public StructTimespec(long, long);
+    method public int compareTo(android.system.StructTimespec);
+    field public final long tv_nsec;
+    field public final long tv_sec;
+  }
+
   public final class StructUtsname {
     ctor public StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     field public final java.lang.String machine;
@@ -49500,7 +49502,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
-    method public static void setSafeBrowsingWhiteList(java.util.List<java.lang.String>);
+    method public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 22e4c1f..ca34142 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -267,6 +267,14 @@
 
 }
 
+package android.net.wifi {
+
+  public class WifiManager {
+    method public deprecated boolean setWifiApEnabled(android.net.wifi.WifiConfiguration, boolean);
+  }
+
+}
+
 package android.os {
 
   public class BatteryManager {
diff --git a/core/java/android/app/timezone/Callback.java b/core/java/android/app/timezone/Callback.java
index b51e5ba..aea8038 100644
--- a/core/java/android/app/timezone/Callback.java
+++ b/core/java/android/app/timezone/Callback.java
@@ -27,7 +27,6 @@
  *
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
 public abstract class Callback {
 
     @Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/app/timezone/DistroFormatVersion.java b/core/java/android/app/timezone/DistroFormatVersion.java
index e879e8f..be732e4 100644
--- a/core/java/android/app/timezone/DistroFormatVersion.java
+++ b/core/java/android/app/timezone/DistroFormatVersion.java
@@ -35,7 +35,6 @@
  *
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
 public final class DistroFormatVersion implements Parcelable {
 
     private final int mMajorVersion;
diff --git a/core/java/android/app/timezone/DistroRulesVersion.java b/core/java/android/app/timezone/DistroRulesVersion.java
index 1eb9f45..a680594 100644
--- a/core/java/android/app/timezone/DistroRulesVersion.java
+++ b/core/java/android/app/timezone/DistroRulesVersion.java
@@ -36,7 +36,6 @@
  *
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
 public final class DistroRulesVersion implements Parcelable {
 
     private final String mRulesVersion;
diff --git a/core/java/android/app/timezone/RulesManager.java b/core/java/android/app/timezone/RulesManager.java
index 649d894..ad9b698 100644
--- a/core/java/android/app/timezone/RulesManager.java
+++ b/core/java/android/app/timezone/RulesManager.java
@@ -64,7 +64,6 @@
  * {@link Context#TIME_ZONE_RULES_MANAGER_SERVICE}.
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
 public final class RulesManager {
     private static final String TAG = "timezone.RulesManager";
     private static final boolean DEBUG = false;
diff --git a/core/java/android/app/timezone/RulesState.java b/core/java/android/app/timezone/RulesState.java
index 7d6ad21..ec247eb 100644
--- a/core/java/android/app/timezone/RulesState.java
+++ b/core/java/android/app/timezone/RulesState.java
@@ -60,7 +60,6 @@
  *
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
 public final class RulesState implements Parcelable {
 
     @Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/app/timezone/RulesUpdaterContract.java b/core/java/android/app/timezone/RulesUpdaterContract.java
index 07b2f33..9c62f46 100644
--- a/core/java/android/app/timezone/RulesUpdaterContract.java
+++ b/core/java/android/app/timezone/RulesUpdaterContract.java
@@ -27,7 +27,6 @@
  *
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
 public final class RulesUpdaterContract {
 
     /**
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index ed41e79..aa9562f 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -608,15 +608,15 @@
     }
 
     /**
-     * Get {@link ApplicationInfo} for a profile
+     * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
      *
      * @param packageName The package name of the application
      * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
      * @param user The UserHandle of the profile.
      *
-     * @return An {@link ApplicationInfo} containing information about the package or
-     *         null if the package isn't installed for the given user, or the target user
-     *         is not enabled.
+     * @return {@link ApplicationInfo} containing information about the package. Returns
+     *         {@code null} if the package isn't installed for the given profile, or the profile
+     *         isn't enabled.
      */
     public ApplicationInfo getApplicationInfo(@NonNull String packageName,
             @ApplicationInfoFlags int flags, @NonNull UserHandle user)
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 9b5d0d3..5b15c0d 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Build;
@@ -257,6 +258,7 @@
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean resetDevice() {
         return native_reset_device();
     }
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 2d9860c..4b79cbb 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -99,7 +99,7 @@
  *       shut down the tunnel gracefully.</li>
  * </ol>
  *
- * <p>Services extended this class need to be declared with appropriate
+ * <p>Services extending this class need to be declared with an appropriate
  * permission and intent filter. Their access must be secured by
  * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and
  * their intent filter must match {@link #SERVICE_INTERFACE} action. Here
@@ -112,6 +112,13 @@
  *     &lt;/intent-filter&gt;
  * &lt;/service&gt;</pre>
  *
+ * <p> The Android system starts a VPN in the background by calling
+ * {@link android.content.Context#startService startService()}. In Android 8.0
+ * (API level 26) and higher, the system places VPN apps on the temporary
+ * whitelist for a short period so the app can start in the background. The VPN
+ * app must promote itself to the foreground after it's launched or the system
+ * will shut down the app.
+ *
  * @see Builder
  */
 public class VpnService extends Service {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a34668c..41f090a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -16,15 +16,6 @@
 
 package android.os;
 
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import android.app.job.JobParameters;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -43,6 +34,15 @@
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * A class providing access to battery usage statistics, including information on
  * wakelocks, processes, packages, and services.  All times are represented in microseconds
@@ -168,6 +168,11 @@
     public static final int BLUETOOTH_UNOPTIMIZED_SCAN_ON = 21;
 
     /**
+     * A constant indicating a foreground service timer
+     */
+    public static final int FOREGROUND_SERVICE = 22;
+
+    /**
      * Include all of the data in the stats, including previously saved data.
      */
     public static final int STATS_SINCE_CHARGED = 0;
@@ -223,7 +228,11 @@
     private static final String CPU_TIMES_AT_FREQ_DATA = "ctf";
     private static final String SENSOR_DATA = "sr";
     private static final String VIBRATOR_DATA = "vib";
-    private static final String FOREGROUND_DATA = "fg";
+    private static final String FOREGROUND_ACTIVITY_DATA = "fg";
+    // fgs line is:
+    // BATTERY_STATS_CHECKIN_VERSION, uid, category, "fgs",
+    // foreground service time, count
+    private static final String FOREGROUND_SERVICE_DATA = "fgs";
     private static final String STATE_TIME_DATA = "st";
     // wl line is:
     // BATTERY_STATS_CHECKIN_VERSION, uid, which, "wl", name,
@@ -582,6 +591,11 @@
         public abstract Timer getFlashlightTurnedOnTimer();
         public abstract Timer getCameraTurnedOnTimer();
         public abstract Timer getForegroundActivityTimer();
+
+        /**
+         * Returns the timer keeping track of Foreground Service time
+         */
+        public abstract Timer getForegroundServiceTimer();
         public abstract Timer getBluetoothScanTimer();
         public abstract Timer getBluetoothScanBackgroundTimer();
         public abstract Timer getBluetoothUnoptimizedScanTimer();
@@ -3616,7 +3630,10 @@
             dumpTimer(pw, uid, category, VIBRATOR_DATA, u.getVibratorOnTimer(),
                     rawRealtime, which);
 
-            dumpTimer(pw, uid, category, FOREGROUND_DATA, u.getForegroundActivityTimer(),
+            dumpTimer(pw, uid, category, FOREGROUND_ACTIVITY_DATA, u.getForegroundActivityTimer(),
+                    rawRealtime, which);
+
+            dumpTimer(pw, uid, category, FOREGROUND_SERVICE_DATA, u.getForegroundServiceTimer(),
                     rawRealtime, which);
 
             final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
@@ -5093,6 +5110,8 @@
                     "Vibrator");
             uidActivity |= printTimer(pw, sb, u.getForegroundActivityTimer(), rawRealtime, which,
                     prefix, "Foreground activities");
+            uidActivity |= printTimer(pw, sb, u.getForegroundServiceTimer(), rawRealtime, which,
+                    prefix, "Foreground services");
 
             long totalStateTime = 0;
             for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 52dccb4..51b7798 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -18,9 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.app.Activity;
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.content.ComponentName;
@@ -142,7 +142,6 @@
      * @see #getPrintServices
      * @hide
      */
-    @TestApi
     public static final int ALL_SERVICES = ENABLED_SERVICES | DISABLED_SERVICES;
 
     /**
@@ -554,6 +553,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICES)
     public void addPrintServicesChangeListener(@NonNull PrintServicesChangeListener listener,
             @Nullable Handler handler) {
         Preconditions.checkNotNull(listener);
@@ -589,6 +589,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICES)
     public void removePrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) {
         Preconditions.checkNotNull(listener);
 
@@ -629,8 +630,8 @@
      *
      * @hide
      */
-    @TestApi
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICES)
     public @NonNull List<PrintServiceInfo> getPrintServices(int selectionFlags) {
         Preconditions.checkFlagsArgument(selectionFlags, ALL_SERVICES);
 
@@ -656,6 +657,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS)
     public void addPrintServiceRecommendationsChangeListener(
             @NonNull PrintServiceRecommendationsChangeListener listener,
             @Nullable Handler handler) {
@@ -692,6 +694,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS)
     public void removePrintServiceRecommendationsChangeListener(
             @NonNull PrintServiceRecommendationsChangeListener listener) {
         Preconditions.checkNotNull(listener);
@@ -731,6 +734,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS)
     public @NonNull List<RecommendationInfo> getPrintServiceRecommendations() {
         try {
             List<RecommendationInfo> recommendations =
diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java
index 5ef9319..57f1229 100644
--- a/core/java/android/printservice/PrintServiceInfo.java
+++ b/core/java/android/printservice/PrintServiceInfo.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
-import android.annotation.TestApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -49,7 +48,6 @@
  *
  * @hide
  */
-@TestApi
 @SystemApi
 public final class PrintServiceInfo implements Parcelable {
 
diff --git a/core/java/android/provider/TimeZoneRulesDataContract.java b/core/java/android/provider/TimeZoneRulesDataContract.java
index a607563..33d2588 100644
--- a/core/java/android/provider/TimeZoneRulesDataContract.java
+++ b/core/java/android/provider/TimeZoneRulesDataContract.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 
 /**
@@ -24,7 +25,7 @@
  *
  * @hide
  */
-// TODO(nfuller): Expose necessary APIs for OEMs with @SystemApi. http://b/31008728
+@SystemApi
 public final class TimeZoneRulesDataContract {
 
     private TimeZoneRulesDataContract() {}
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 137cf57..ce678fc 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -17,7 +17,7 @@
 
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
-import android.app.NotificationChannel;
+import android.app.Notification;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -48,6 +48,12 @@
      * {@link NotificationAssistantService#onNotificationSnoozedUntilContext}.
      */
     public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
+    /**
+     * Data type: String. Used to change what {@link Notification#getGroup() group} a notification
+     * belongs to.
+     * @hide
+     */
+    public static final String KEY_GROUP_KEY = "key_group_key";
 
     /**
      * Create a notification adjustment.
@@ -146,4 +152,11 @@
         dest.writeBundle(mSignals);
         dest.writeInt(mUser);
     }
+
+    @Override
+    public String toString() {
+        return "Adjustment{"
+                + "mSignals=" + mSignals
+                + '}';
+    }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ed2547f..4c38266 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1645,9 +1645,13 @@
      * TODO: Add documentation for the format of the urls.
      *
      * @param urls the list of URLs
+     * @param callback will be called with true if URLs are successfully added to the whitelist. It
+     * will be called with false if any URLs are malformed. The callback will be run on the UI
+     * thread.
      */
-    public static void setSafeBrowsingWhiteList(@Nullable List<String> urls) {
-        getFactory().getStatics().setSafeBrowsingWhiteList(urls);
+    public static void setSafeBrowsingWhitelist(@Nullable List<String> urls,
+            @Nullable ValueCallback<Boolean> callback) {
+        getFactory().getStatics().setSafeBrowsingWhitelist(urls, callback);
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 9b31a0c..613eb72 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -91,9 +91,10 @@
 
         /**
         * Implement the API method
-        * {@link android.webkit.WebView#setSafeBrowsingWhiteList(List<String>)}
+        * {@link android.webkit.WebView#setSafeBrowsingWhitelist(List<String>,
+        * ValueCallback<Boolean>)}
         */
-        void setSafeBrowsingWhiteList(List<String> urls);
+        void setSafeBrowsingWhitelist(List<String> urls, ValueCallback<Boolean> callback);
     }
 
     Statics getStatics();
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index ebea1a4..04874bd 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -28,6 +28,7 @@
 import android.graphics.Point;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.CancellationSignal;
 import android.os.FileObserver;
 import android.os.FileUtils;
@@ -68,6 +69,8 @@
 
     private Handler mHandler;
 
+    private static final String MIMETYPE_PDF = "application/pdf";
+
     protected abstract File getFileForDocId(String docId, boolean visible)
             throws FileNotFoundException;
 
@@ -387,6 +390,13 @@
             String documentId, Point sizeHint, CancellationSignal signal)
             throws FileNotFoundException {
         final File file = getFileForDocId(documentId);
+        if (getTypeForFile(file).equals(MIMETYPE_PDF)) {
+            try {
+                return PdfUtils.openPdfThumbnail(file, sizeHint);
+            } catch (Exception e) {
+                Log.v(TAG, "Could not load PDF's thumbnail", e);
+            }
+        }
         return DocumentsContract.openImageThumbnail(file);
     }
 
@@ -416,7 +426,10 @@
 
         final String mimeType = getTypeForFile(file);
         final String displayName = file.getName();
-        if (mimeType.startsWith("image/")) {
+        // As of right now, we aren't sure on the performance affect of loading all PDF Thumbnails
+        // Until a solution is found, it will be behind a debuggable flag.
+        if (mimeType.startsWith("image/")
+                || (mimeType.equals(MIMETYPE_PDF) && Build.IS_DEBUGGABLE)) {
             flags |= Document.FLAG_SUPPORTS_THUMBNAIL;
         }
 
diff --git a/core/java/com/android/internal/content/PdfUtils.java b/core/java/com/android/internal/content/PdfUtils.java
new file mode 100644
index 0000000..1716d42
--- /dev/null
+++ b/core/java/com/android/internal/content/PdfUtils.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.content;
+
+import android.annotation.Nullable;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.pdf.PdfRenderer;
+import android.os.AsyncTask;
+import android.os.ParcelFileDescriptor;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Utils class for extracting PDF Thumbnails
+ */
+public final class PdfUtils {
+
+    private PdfUtils() {
+    }
+
+    /**
+     * Returns the front page of the pdf as a thumbnail
+     * @param file Given PDF File
+     * @param size Cropping of the front page.
+     * @return AssetFileDescriptor containing the thumbnail as a bitmap.
+     * @throws IOException if the file isn't a pdf or if the file doesn't exist.
+     */
+    public static @Nullable AssetFileDescriptor openPdfThumbnail(File file, Point size)
+            throws IOException {
+        // Create the bitmap of the PDF's first page
+        ParcelFileDescriptor pdfDescriptor =
+                ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+        PdfRenderer renderer = new PdfRenderer(pdfDescriptor);
+        PdfRenderer.Page frontPage = renderer.openPage(0);
+        Bitmap thumbnail = Bitmap.createBitmap(size.x, size.y,
+                Bitmap.Config.ARGB_8888);
+        frontPage.render(thumbnail, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
+
+        // Create an AssetFileDescriptor that contains the Bitmap's information
+        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+        // Quality is an integer that determines how much compression is used.
+        // However, this integer is ignored when using the PNG format
+        int quality = 100;
+        // The use of Bitmap.CompressFormat.JPEG leads to a black PDF background on the thumbnail
+        thumbnail.compress(Bitmap.CompressFormat.PNG, quality, out);
+
+        final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+
+        final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createReliablePipe();
+        new AsyncTask<Object, Object, Object>() {
+            @Override
+            protected Object doInBackground(Object... params) {
+                final FileOutputStream fos = new FileOutputStream(fds[1].getFileDescriptor());
+                try {
+                    Streams.copy(in, fos);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+                IoUtils.closeQuietly(fds[1]);
+                try {
+                    pdfDescriptor.close();
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+                return null;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        pdfDescriptor.close();
+        return new AssetFileDescriptor(fds[0], 0, AssetFileDescriptor.UNKNOWN_LENGTH);
+    }
+
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fa23e40..c7f619d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -119,7 +119,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 160 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 161 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS;
@@ -5637,6 +5637,7 @@
         StopwatchTimer mFlashlightTurnedOnTimer;
         StopwatchTimer mCameraTurnedOnTimer;
         StopwatchTimer mForegroundActivityTimer;
+        StopwatchTimer mForegroundServiceTimer;
         /** Total time spent by the uid holding any partial wakelocks. */
         DualTimer mAggregatedPartialWakelockTimer;
         DualTimer mBluetoothScanTimer;
@@ -5647,6 +5648,8 @@
         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         StopwatchTimer[] mProcessStateTimer;
 
+        boolean mInForegroundService = false;
+
         BatchTimer mVibratorOnTimer;
 
         Counter[] mUserActivityCounters;
@@ -6119,6 +6122,14 @@
             return mForegroundActivityTimer;
         }
 
+        public StopwatchTimer createForegroundServiceTimerLocked() {
+            if (mForegroundServiceTimer == null) {
+                mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+                        FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase);
+            }
+            return mForegroundServiceTimer;
+        }
+
         public DualTimer createAggregatedPartialWakelockTimerLocked() {
             if (mAggregatedPartialWakelockTimer == null) {
                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
@@ -6207,6 +6218,16 @@
             }
         }
 
+        public void noteForegroundServiceResumedLocked(long elapsedRealtimeMs) {
+            createForegroundServiceTimerLocked().startRunningLocked(elapsedRealtimeMs);
+        }
+
+        public void noteForegroundServicePausedLocked(long elapsedRealtimeMs) {
+            if (mForegroundServiceTimer != null) {
+                mForegroundServiceTimer.stopRunningLocked(elapsedRealtimeMs);
+            }
+        }
+
         public BatchTimer createVibratorOnTimerLocked() {
             if (mVibratorOnTimer == null) {
                 mVibratorOnTimer = new BatchTimer(mBsi.mClocks, Uid.this, VIBRATOR_ON,
@@ -6335,6 +6356,11 @@
         }
 
         @Override
+        public Timer getForegroundServiceTimer() {
+            return mForegroundServiceTimer;
+        }
+
+        @Override
         public Timer getBluetoothScanTimer() {
             return mBluetoothScanTimer;
         }
@@ -6618,6 +6644,7 @@
             active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
             active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
+            active |= !resetTimerIfNotNull(mForegroundServiceTimer, false);
             active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
             active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
@@ -6817,6 +6844,10 @@
                     mForegroundActivityTimer.detach();
                     mForegroundActivityTimer = null;
                 }
+                if (mForegroundServiceTimer != null) {
+                    mForegroundServiceTimer.detach();
+                    mForegroundServiceTimer = null;
+                }
                 if (mAggregatedPartialWakelockTimer != null) {
                     mAggregatedPartialWakelockTimer.detach();
                     mAggregatedPartialWakelockTimer = null;
@@ -7026,6 +7057,12 @@
             } else {
                 out.writeInt(0);
             }
+            if (mForegroundServiceTimer != null) {
+                out.writeInt(1);
+                mForegroundServiceTimer.writeToParcel(out, elapsedRealtimeUs);
+            } else {
+                out.writeInt(0);
+            }
             if (mAggregatedPartialWakelockTimer != null) {
                 out.writeInt(1);
                 mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
@@ -7305,6 +7342,12 @@
                 mForegroundActivityTimer = null;
             }
             if (in.readInt() != 0) {
+                mForegroundServiceTimer = new StopwatchTimer(mBsi.mClocks, Uid.this,
+                        FOREGROUND_SERVICE, null, mBsi.mOnBatteryTimeBase, in);
+            } else {
+                mForegroundServiceTimer = null;
+            }
+            if (in.readInt() != 0) {
                 mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
                         AGGREGATED_WAKE_TYPE_PARTIAL, null,
                         mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
@@ -8350,6 +8393,9 @@
 
         public void updateUidProcessStateLocked(int procState) {
             int uidRunningState;
+            // Make special note of Foreground Services
+            final boolean userAwareService =
+                    (procState == ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
             if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
                 uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
@@ -8368,24 +8414,37 @@
                 uidRunningState = PROCESS_STATE_CACHED;
             }
 
-            if (mProcessState == uidRunningState) return;
+            if (mProcessState == uidRunningState && userAwareService == mInForegroundService) {
+                return;
+            }
 
             final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime();
-            final long uptimeMs = mBsi.mClocks.uptimeMillis();
+            if (mProcessState != uidRunningState) {
+                final long uptimeMs = mBsi.mClocks.uptimeMillis();
 
-            if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
-                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
-            }
-            mProcessState = uidRunningState;
-            if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
-                if (mProcessStateTimer[uidRunningState] == null) {
-                    makeProcessState(uidRunningState, null);
+                if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                    mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
                 }
-                mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
+                mProcessState = uidRunningState;
+                if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                    if (mProcessStateTimer[uidRunningState] == null) {
+                        makeProcessState(uidRunningState, null);
+                    }
+                    mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
+                }
+
+                updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
+                updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
             }
 
-            updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
-            updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
+            if (userAwareService != mInForegroundService) {
+                if (userAwareService) {
+                    noteForegroundServiceResumedLocked(elapsedRealtimeMs);
+                } else {
+                    noteForegroundServicePausedLocked(elapsedRealtimeMs);
+                }
+                mInForegroundService = userAwareService;
+            }
         }
 
         /** Whether to consider Uid to be in the background for background timebase purposes. */
@@ -11610,6 +11669,9 @@
                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
+                u.createForegroundServiceTimerLocked().readSummaryFromParcelLocked(in);
+            }
+            if (in.readInt() != 0) {
                 u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
@@ -12021,6 +12083,12 @@
             } else {
                 out.writeInt(0);
             }
+            if (u.mForegroundServiceTimer != null) {
+                out.writeInt(1);
+                u.mForegroundServiceTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+            } else {
+                out.writeInt(0);
+            }
             if (u.mAggregatedPartialWakelockTimer != null) {
                 out.writeInt(1);
                 u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 4f9e8a5..18990cf 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -217,6 +217,8 @@
                     "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG");
             addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
                     "/sys/fs/pstore/console-ramoops", -LOG_SIZE, "SYSTEM_LAST_KMSG");
+            addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
+                    "/sys/fs/pstore/console-ramoops-0", -LOG_SIZE, "SYSTEM_LAST_KMSG");
             addFileToDropBox(db, timestamps, headers, "/cache/recovery/log", -LOG_SIZE,
                     "SYSTEM_RECOVERY_LOG");
             addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
@@ -302,6 +304,10 @@
         if (fileTime <= 0) {
             file = new File("/sys/fs/pstore/console-ramoops");
             fileTime = file.lastModified();
+            if (fileTime <= 0) {
+                file = new File("/sys/fs/pstore/console-ramoops-0");
+                fileTime = file.lastModified();
+            }
         }
 
         if (fileTime <= 0) return;  // File does not exist
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3e3585b..f5d3a29 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2534,6 +2534,23 @@
     <permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
             android:protectionLevel="signature" />
 
+    <!-- Allows applications to get the installed and enabled print services.
+         @hide
+         @SystemApi
+         @TestApi
+         <p>Protection level: signature|preinstalled
+    -->
+    <permission android:name="android.permission.READ_PRINT_SERVICES"
+        android:protectionLevel="signature|preinstalled" />
+
+    <!-- Allows applications to get the currently recommended print services for printers.
+         @hide
+         @SystemApi
+         <p>Protection level: signature|preinstalled
+    -->
+    <permission android:name="android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS"
+        android:protectionLevel="signature|preinstalled" />
+
     <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
          or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
          the system can bind to it.
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 94b988e..a088a46 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -106,12 +106,6 @@
         <item>@drawable/progress_large_material</item>
         <item>@drawable/progress_medium_material</item>
         <item>@drawable/progress_small_material</item>
-        <item>@drawable/quickcontact_badge_overlay_dark</item>
-        <item>@drawable/quickcontact_badge_overlay_light</item>
-        <item>@drawable/quickcontact_badge_overlay_normal_dark</item>
-        <item>@drawable/quickcontact_badge_overlay_normal_light</item>
-        <item>@drawable/quickcontact_badge_overlay_pressed_dark</item>
-        <item>@drawable/quickcontact_badge_overlay_pressed_light</item>
         <item>@drawable/ratingbar_indicator_material</item>
         <item>@drawable/ratingbar_material</item>
         <item>@drawable/ratingbar_small_material</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ceb7ccd..be1c4b8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2230,11 +2230,19 @@
     <string-array name="config_disabledUntilUsedPreinstalledCarrierApps" translatable="false" />
 
     <!-- The list of classes that should be added to the notification ranking pipline.
-     See {@link com.android.server.notification.NotificationSignalExtractor} -->
+     See {@link com.android.server.notification.NotificationSignalExtractor}
+      If you add a new extractor to this list make sure to update
+      NotificationManagerService.handleRankingSort()-->
     <string-array name="config_notificationSignalExtractors">
+        <!-- many of the following extractors depend on the notification channel, so this
+        extractor must come first -->
+        <item>com.android.server.notification.NotificationChannelExtractor</item>
+        <item>com.android.server.notification.NotificationAdjustmentExtractor</item>
+        <!-- depends on AdjustmentExtractor-->
         <item>com.android.server.notification.ValidateNotificationPeople</item>
         <item>com.android.server.notification.PriorityExtractor</item>
         <item>com.android.server.notification.ImportanceExtractor</item>
+        <!-- depends on ImportanceExtractor-->
         <item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
         <item>com.android.server.notification.VisibilityExtractor</item>
         <item>com.android.server.notification.BadgeExtractor</item>
diff --git a/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java b/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
index 9bbcd3d..70a0877 100644
--- a/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
+++ b/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
@@ -27,7 +27,6 @@
 /**
  * Tests for {@link DistroFormatVersion}.
  */
-// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
 public class DistroFormatVersionTest {
 
     @Test
diff --git a/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java b/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
index 2fbc9a1..eecae46 100644
--- a/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
+++ b/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
@@ -27,7 +27,6 @@
 /**
  * Tests for {@link DistroRulesVersion}.
  */
-// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
 public class DistroRulesVersionTest {
 
     @Test
diff --git a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
index 7f4819b..99abe24 100644
--- a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
+++ b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
@@ -29,7 +29,6 @@
 /**
  * Tests for {@link RulesState}.
  */
-// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
 public class RulesStateTest {
 
     @Test
diff --git a/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java b/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
index e7a839c..91f8ebc 100644
--- a/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
+++ b/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
@@ -33,7 +33,6 @@
 /**
  * Tests for {@link RulesUpdaterContract}.
  */
-// TODO(nfuller) Move to CTS once this class is part of the SystemApi. http://b/31008728
 public class RulesUpdaterContractTest {
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 4e8ab31..fa3d34a 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -25,8 +25,22 @@
 
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Test various BatteryStatsImpl noteStart methods.
+ *
+ * Build/Install/Run: bit FrameworksCoreTests:com.android.internal.os.BatteryStatsNoteTest
+ *
+ * Alternatively,
+ * Build: m FrameworksCoreTests
+ * Install: adb install -r \
+ *      ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsNoteTest -w \
+ *      com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
  */
 public class BatteryStatsNoteTest extends TestCase{
     private static final int UID = 10500;
@@ -86,4 +100,95 @@
         assertEquals(220_000, actualTime);
         assertEquals(120_000, bgTime);
     }
+
+
+    /** Test BatteryStatsImpl.noteUidProcessStateLocked. */
+    @SmallTest
+    public void testNoteUidProcessStateLocked() throws Exception {
+        final MockClocks clocks = new MockClocks();
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+        // map of ActivityManager process states and how long to simulate run time in each state
+        Map<Integer, Integer> stateRuntimeMap = new HashMap<Integer, Integer>();
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TOP, 1111);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 1234);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 2468);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TOP_SLEEPING, 7531);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 4455);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 1337);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_BACKUP, 90210);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_HEAVY_WEIGHT, 911);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_SERVICE, 404);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_RECEIVER, 31459);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_HOME, 1123);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_LAST_ACTIVITY, 5813);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, 867);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT, 5309);
+        stateRuntimeMap.put(ActivityManager.PROCESS_STATE_CACHED_EMPTY, 42);
+
+        bi.updateTimeBasesLocked(true, false, 0, 0);
+
+        for (Map.Entry<Integer, Integer> entry : stateRuntimeMap.entrySet()) {
+            bi.noteUidProcessStateLocked(UID, entry.getKey());
+            clocks.realtime += entry.getValue();
+            clocks.uptime = clocks.realtime;
+        }
+
+        long actualRunTimeUs;
+        long expectedRunTimeMs;
+        long elapsedTimeUs = clocks.realtime * 1000;
+        BatteryStats.Uid uid = bi.getUidStats().get(UID);
+
+        // compare runtime of process states to the Uid process states they map to
+        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP, elapsedTimeUs,
+                STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+
+
+        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
+                elapsedTimeUs, STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(
+                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+
+
+        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
+                elapsedTimeUs, STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+
+
+        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND,
+                elapsedTimeUs, STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+
+
+        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND,
+                elapsedTimeUs, STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_BACKUP)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_HEAVY_WEIGHT)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_SERVICE)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_RECEIVER);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+
+
+        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_CACHED,
+                elapsedTimeUs, STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_HOME)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_LAST_ACTIVITY)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT)
+                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+
+        // Special check for foreground service timer
+        actualRunTimeUs = uid.getForegroundServiceTimer().getTotalTimeLocked(elapsedTimeUs,
+                STATS_SINCE_CHARGED);
+        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
index 4a23f40..27aec56 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
@@ -114,7 +114,7 @@
     public void testOnTimeStarted() {
         initializeCounterArrayWithDefaultValues();
         mCounterArray.onTimeStarted(0, 0, 0);
-        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
         assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
         assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
         assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
@@ -150,6 +150,7 @@
     @Test
     public void testAddCountLocked() {
         final long[] deltas = {123, 234, 345, 456};
+        when(mTimeBase.isRunning()).thenReturn(true);
         mCounterArray.addCountLocked(deltas);
         assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
         assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
diff --git a/media/jni/midi/android_media_midi_MidiDevice.cpp b/media/jni/midi/android_media_midi_MidiDevice.cpp
index 4df8436..5b35453 100644
--- a/media/jni/midi/android_media_midi_MidiDevice.cpp
+++ b/media/jni/midi/android_media_midi_MidiDevice.cpp
@@ -18,8 +18,8 @@
 #define LOG_TAG "Midi-JNI"
 
 #include <android_util_Binder.h>
+#include <jni.h>
 #include <midi_internal.h>
-#include <nativehelper/jni.h>
 #include <utils/Log.h>
 
 using namespace android;
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 4b9415e..91e23dd 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -36,6 +36,8 @@
     <uses-permission android:name="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"/>
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+    <uses-permission android:name="android.permission.READ_PRINT_SERVICES" />
+    <uses-permission android:name="android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS" />
 
     <application
         android:allowClearUserData="true"
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java
new file mode 100644
index 0000000..75b6696
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.development;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v4.content.LocalBroadcastManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.TwoStatePreference;
+import android.text.TextUtils;
+
+import com.android.settingslib.core.AbstractPreferenceController;
+
+public abstract class AbstractEnableAdbPreferenceController extends AbstractPreferenceController {
+    private static final String KEY_ENABLE_ADB = "enable_adb";
+    public static final String ACTION_ENABLE_ADB_STATE_CHANGED =
+            "com.android.settingslib.development.AbstractEnableAdbController."
+                    + "ENABLE_ADB_STATE_CHANGED";
+
+    private SwitchPreference mPreference;
+
+    public AbstractEnableAdbPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        if (isAvailable()) {
+            mPreference = (SwitchPreference) screen.findPreference(KEY_ENABLE_ADB);
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mContext.getSystemService(UserManager.class).isAdminUser();
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_ENABLE_ADB;
+    }
+
+    private boolean isAdbEnabled() {
+        final ContentResolver cr = mContext.getContentResolver();
+        return Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) != 0;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        ((TwoStatePreference)preference).setChecked(isAdbEnabled());
+    }
+
+    public void enablePreference(boolean enabled) {
+        if (isAvailable()) {
+            mPreference.setEnabled(enabled);
+        }
+    }
+
+    public void resetPreference() {
+        if (mPreference.isChecked()) {
+            mPreference.setChecked(false);
+            handlePreferenceTreeClick(mPreference);
+        }
+    }
+
+    public boolean haveDebugSettings() {
+        return isAdbEnabled();
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (TextUtils.equals(KEY_ENABLE_ADB, preference.getKey())) {
+            if (!isAdbEnabled()) {
+                showConfirmationDialog((SwitchPreference) preference);
+            } else {
+                writeAdbSetting(false);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected void writeAdbSetting(boolean enabled) {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.ADB_ENABLED, enabled ? 1 : 0);
+        notifyStateChanged();
+    }
+
+    protected void notifyStateChanged() {
+        LocalBroadcastManager.getInstance(mContext)
+                .sendBroadcast(new Intent(ACTION_ENABLE_ADB_STATE_CHANGED));
+    }
+
+    public abstract void showConfirmationDialog(SwitchPreference preference);
+}
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index eca2052..55b635e 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -41,7 +41,7 @@
 
 # Include the testing libraries (JUnit4 + Robolectric libs).
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    platform-system-robolectric \
+    mockito-robolectric-prebuilt \
     truth-prebuilt
 
 LOCAL_JAVA_LIBRARIES := \
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
new file mode 100644
index 0000000..0778b27
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settingslib.SettingLibRobolectricTestRunner;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class EnableAdbPreferenceControllerTest {
+    @Mock(answer = RETURNS_DEEP_STUBS)
+    private PreferenceScreen mScreen;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private PackageManager mPackageManager;
+
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private ConcreteEnableAdbPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication shadowContext = ShadowApplication.getInstance();
+        shadowContext.setSystemService(Context.USER_SERVICE, mUserManager);
+        mContext = spy(shadowContext.getApplicationContext());
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        mPreference = new SwitchPreference(mContext);
+        when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+        mController = new ConcreteEnableAdbPreferenceController(mContext);
+        mPreference.setKey(mController.getPreferenceKey());
+    }
+
+    @Test
+    public void displayPreference_isNotAdmin_shouldRemovePreference() {
+        when(mUserManager.isAdminUser()).thenReturn(false);
+        when(mScreen.getPreferenceCount()).thenReturn(1);
+        when(mScreen.getPreference(0)).thenReturn(mPreference);
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen).removePreference(any(Preference.class));
+    }
+
+    @Test
+    public void displayPreference_isAdmin_shouldNotRemovePreference() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+
+        mController.displayPreference(mScreen);
+
+        verify(mScreen, never()).removePreference(any(Preference.class));
+    }
+
+
+    @Test
+    public void resetPreference_shouldUncheck() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        mController.displayPreference(mScreen);
+        mPreference.setChecked(true);
+
+        mController.resetPreference();
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_shouldUpdateSettings() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.ADB_ENABLED, 1);
+        mPreference.setChecked(true);
+        mController.displayPreference(mScreen);
+
+        mController.handlePreferenceTreeClick(mPreference);
+
+        assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Global.ADB_ENABLED, 0)).isEqualTo(0);
+    }
+
+    @Test
+    public void updateState_settingsOn_shouldCheck() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.ADB_ENABLED, 1);
+        mPreference.setChecked(false);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_settingsOff_shouldUncheck() {
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Global.ADB_ENABLED, 0);
+        mPreference.setChecked(true);
+        mController.displayPreference(mScreen);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    class ConcreteEnableAdbPreferenceController extends AbstractEnableAdbPreferenceController {
+        public ConcreteEnableAdbPreferenceController(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void showConfirmationDialog(SwitchPreference preference) {
+            // Don't show a dialog, just set setting.
+            writeAdbSetting(true);
+        }
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 0364418..e9ca753 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -18,11 +18,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -59,7 +60,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -100,6 +100,7 @@
         MockitoAnnotations.initMocks(this);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getResourcesForApplication(anyString())).thenReturn(mResources);
+        when(mPackageManager.getResourcesForApplication((String) isNull())).thenReturn(mResources);
         when(mPackageManager.getApplicationInfo(eq("abc"), anyInt()))
                 .thenReturn(application.getApplicationInfo());
         mContentResolver = spy(application.getContentResolver());
@@ -115,7 +116,6 @@
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         info.add(newInfo(true, testCategory));
-        Map<Pair<String, String>, Tile> cache = new ArrayMap<>();
         when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
                 .thenReturn(info);
 
@@ -169,7 +169,6 @@
 
     @Test
     public void getTilesForIntent_shouldSkipFilteredApps() {
-        final String testCategory = "category1";
         Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
@@ -210,11 +209,9 @@
         userHandleList.add(UserHandle.CURRENT);
         when(mUserManager.getUserProfiles()).thenReturn(userHandleList);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(argThat(new ArgumentMatcher<Intent>() {
-            public boolean matches(Object event) {
-                return testAction.equals(((Intent) event).getAction());
-            }
-        }), anyInt(), anyInt())).thenReturn(info);
+        when(mPackageManager.queryIntentActivitiesAsUser(argThat(
+                event -> testAction.equals(event.getAction())), anyInt(), anyInt()))
+                .thenReturn(info);
 
         List<DashboardCategory> categoryList = TileUtils.getCategories(
                 mContext, cache, false /* categoryDefinedInManifest */, testAction,
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 44fae86..ee14f3d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -28,41 +28,46 @@
     androidprv:layout_maxWidth="@dimen/keyguard_security_width"
     androidprv:layout_maxHeight="@dimen/keyguard_security_height"
     android:gravity="center_horizontal|top">
-    <RelativeLayout
-        android:id="@+id/keyguard_clock_container"
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal|top">
-        <TextClock
-            android:id="@+id/clock_view"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:layout_centerHorizontal="true"
-            android:layout_alignParentTop="true"
-            android:textColor="?attr/bgProtectTextColor"
-            android:singleLine="true"
-            style="@style/widget_big_thin"
-            android:format12Hour="@string/keyguard_widget_12_hours_format"
-            android:format24Hour="@string/keyguard_widget_24_hours_format"
-            android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
-        <com.android.systemui.ChargingView
-            android:id="@+id/battery_doze"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignTop="@id/clock_view"
-            android:layout_alignBottom="@id/clock_view"
-            android:layout_toEndOf="@id/clock_view"
-            android:visibility="invisible"
-            android:src="@drawable/ic_aod_charging_24dp"
-            android:contentDescription="@string/accessibility_ambient_display_charging"
-        />
-
-        <include layout="@layout/keyguard_status_area"
-            android:id="@+id/keyguard_status_area"
+        android:orientation="vertical">
+        <RelativeLayout
+            android:id="@+id/keyguard_clock_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_below="@id/clock_view" />
+            android:layout_gravity="center_horizontal|top">
+            <TextClock
+                android:id="@+id/clock_view"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_centerHorizontal="true"
+                android:layout_alignParentTop="true"
+                android:textColor="?attr/bgProtectTextColor"
+                android:singleLine="true"
+                style="@style/widget_big_thin"
+                android:format12Hour="@string/keyguard_widget_12_hours_format"
+                android:format24Hour="@string/keyguard_widget_24_hours_format"
+                android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
+            <com.android.systemui.ChargingView
+                android:id="@+id/battery_doze"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignTop="@id/clock_view"
+                android:layout_alignBottom="@id/clock_view"
+                android:layout_toEndOf="@id/clock_view"
+                android:visibility="invisible"
+                android:src="@drawable/ic_aod_charging_24dp"
+                android:contentDescription="@string/accessibility_ambient_display_charging"
+            />
+
+            <include layout="@layout/keyguard_status_area"
+                android:id="@+id/keyguard_status_area"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/clock_view" />
+        </RelativeLayout>
 
         <TextView
             android:id="@+id/owner_info"
@@ -72,12 +77,11 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="@dimen/date_owner_info_margin"
             android:layout_centerHorizontal="true"
-            android:layout_below="@id/keyguard_status_area"
             android:textColor="?attr/bgProtectSecondaryTextColor"
             android:textSize="@dimen/widget_label_font_size"
             android:letterSpacing="0.05"
             android:ellipsize="marquee"
             android:singleLine="true" />
 
-    </RelativeLayout>
+    </LinearLayout>
 </com.android.keyguard.KeyguardStatusView>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 5005f9d..820a773 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -24,6 +24,8 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.support.v4.graphics.ColorUtils;
 import android.text.TextUtils;
@@ -48,6 +50,7 @@
 public class KeyguardStatusView extends GridLayout {
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardStatusView";
+    private static final int MARQUEE_DELAY_MS = 2000;
 
     private final LockPatternUtils mLockPatternUtils;
     private final AlarmManager mAlarmManager;
@@ -59,6 +62,8 @@
     private ViewGroup mClockContainer;
     private ChargingView mBatteryDoze;
     private View mKeyguardStatusArea;
+    private Runnable mPendingMarqueeStart;
+    private Handler mHandler;
 
     private View[] mVisibleInDoze;
     private boolean mPulsing;
@@ -112,9 +117,29 @@
         super(context, attrs, defStyle);
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mLockPatternUtils = new LockPatternUtils(getContext());
+        mHandler = new Handler(Looper.myLooper());
     }
 
     private void setEnableMarquee(boolean enabled) {
+        if (DEBUG) Log.v(TAG, "Schedule setEnableMarquee: " + (enabled ? "Enable" : "Disable"));
+        if (enabled) {
+            if (mPendingMarqueeStart == null) {
+                mPendingMarqueeStart = () -> {
+                    setEnableMarqueeImpl(true);
+                    mPendingMarqueeStart = null;
+                };
+                mHandler.postDelayed(mPendingMarqueeStart, MARQUEE_DELAY_MS);
+            }
+        } else {
+            if (mPendingMarqueeStart != null) {
+                mHandler.removeCallbacks(mPendingMarqueeStart);
+                mPendingMarqueeStart = null;
+            }
+            setEnableMarqueeImpl(false);
+        }
+    }
+
+    private void setEnableMarqueeImpl(boolean enabled) {
         if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
         if (mAlarmStatusView != null) mAlarmStatusView.setSelected(enabled);
         if (mOwnerInfo != null) mOwnerInfo.setSelected(enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index dd3361b..686b3bb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -29,7 +29,7 @@
  */
 public class PipTouchState {
     private static final String TAG = "PipTouchHandler";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private ViewConfiguration mViewConfig;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index fa16f8e..f2ea6a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -337,7 +337,7 @@
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
 
-        mLastConfig = Utilities.getAppConfiguration(this);
+        mLastConfig = new Configuration(Utilities.getAppConfiguration(this));
         mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
         mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index a3e5e45..3e183b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -401,24 +401,6 @@
                 && pm.resolveActivity(PHONE_INTENT, 0) != null;
     }
 
-    private boolean isCameraDisabledByDpm() {
-        final DevicePolicyManager dpm =
-                (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
-        if (dpm != null && mStatusBar != null) {
-            try {
-                final int userId = ActivityManager.getService().getCurrentUser().id;
-                final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
-                final  boolean disabledBecauseKeyguardSecure =
-                        (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
-                                && mStatusBar.isKeyguardSecure();
-                return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Can't get userId", e);
-            }
-        }
-        return false;
-    }
-
     private void watchForCameraPolicyChanges() {
         final IntentFilter filter = new IntentFilter();
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -871,7 +853,8 @@
         @Override
         public IconState getIcon() {
             ResolveInfo resolved = resolveCameraIntent();
-            mIconState.isVisible = !isCameraDisabledByDpm() && resolved != null
+            boolean isCameraDisabled = (mStatusBar != null) && !mStatusBar.isCameraAllowedByAdmin();
+            mIconState.isVisible = !isCameraDisabled && resolved != null
                     && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
                     && mUserSetupComplete;
             mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 3940a15..4ffc15f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2499,6 +2499,10 @@
      * @param keyguardIsShowing whether keyguard is being shown
      */
     public boolean canCameraGestureBeLaunched(boolean keyguardIsShowing) {
+        if (!mStatusBar.isCameraAllowedByAdmin()) {
+            return false;
+        }
+
         ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent();
         String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
                 ? null : resolveInfo.activityInfo.packageName;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 3f5f4da..2afdab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1,5 +1,3 @@
-
-
 /*
  * Copyright (C) 2010 The Android Open Source Project
  *
@@ -104,6 +102,7 @@
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.service.vr.IVrManager;
@@ -565,7 +564,7 @@
         }};
 
     private boolean mWaitingForKeyguardExit;
-    private boolean mDozing;
+    protected boolean mDozing;
     private boolean mDozingRequested;
     protected boolean mScrimSrcModeEnabled;
 
@@ -5280,6 +5279,18 @@
         }
     }
 
+    boolean isCameraAllowedByAdmin() {
+        if (mDevicePolicyManager.getCameraDisabled(null, mCurrentUserId)) {
+            return false;
+        } else if (isKeyguardShowing() && isKeyguardSecure()) {
+            // Check if the admin has disabled the camera specifically for the keyguard
+            return (mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUserId)
+                    & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
+        }
+
+        return true;
+    }
+
     public void notifyFpAuthModeChanged() {
         updateDozing();
     }
@@ -5303,6 +5314,10 @@
     }
 
     public boolean isKeyguardShowing() {
+        if (mStatusBarKeyguardViewManager == null) {
+            Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true");
+            return true;
+        }
         return mStatusBarKeyguardViewManager.isShowing();
     }
 
@@ -5578,6 +5593,10 @@
 
     private Set<String> mNonBlockablePkgs;
 
+    public boolean isDeviceInteractive() {
+        return mDeviceInteractive;
+    }
+
     @Override  // NotificationData.Environment
     public boolean isDeviceProvisioned() {
         return mDeviceProvisionedController.isDeviceProvisioned();
@@ -7227,7 +7246,12 @@
             return false;
         }
 
-        if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
+        if (!isDozing() && mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
+            return false;
+        }
+
+        if (isDozing() && mNotificationData.shouldSuppressScreenOff(sbn.getKey())) {
             if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
             return false;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Util.java b/packages/SystemUI/src/com/android/systemui/volume/Util.java
index a46a44d..c6d6218 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Util.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Util.java
@@ -78,6 +78,7 @@
     }
 
     public static String mediaMetadataToString(MediaMetadata metadata) {
+        if (metadata == null) return null;
         return metadata.getDescription().toString();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index eaad2f9..103eb6e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -48,8 +48,10 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -89,11 +91,12 @@
     private final W mWorker;
     private final Context mContext;
     private AudioManager mAudio;
+    protected StatusBar mStatusBar;
     private final NotificationManager mNoMan;
     private final SettingObserver mObserver;
     private final Receiver mReceiver = new Receiver();
     private final MediaSessions mMediaSessions;
-    private final C mCallbacks = new C();
+    protected C mCallbacks = new C();
     private final State mState = new State();
     private final MediaSessionsCallbacks mMediaSessionsCallbacksW = new MediaSessionsCallbacks();
     private final Vibrator mVibrator;
@@ -123,6 +126,7 @@
         mReceiver.init();
         mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
+        updateStatusBar();
 
         boolean accessibilityVolumeStreamActive = context.getSystemService(
                 AccessibilityManager.class).isAccessibilityVolumeStreamActive();
@@ -326,8 +330,17 @@
         return changed;
     }
 
-    private boolean onVolumeChangedW(int stream, int flags) {
-        final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
+    private void updateStatusBar() {
+        if (mStatusBar == null) {
+            mStatusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
+        }
+    }
+
+    boolean onVolumeChangedW(int stream, int flags) {
+        updateStatusBar();
+
+        final boolean showUI = (mStatusBar != null && mStatusBar.isDeviceInteractive()) &&
+                ((flags & AudioManager.FLAG_SHOW_UI) != 0);
         final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
         final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
         final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0;
@@ -638,7 +651,7 @@
         }
     }
 
-    private final class C implements Callbacks {
+    class C implements Callbacks {
         private final HashMap<Callbacks, Handler> mCallbackMap = new HashMap<>();
 
         public void add(Callbacks callback, Handler handler) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 8a4983c..c33897e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -334,6 +334,83 @@
     }
 
     @Test
+    public void testShouldPeek_suppressedScreenOn_dozing() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = true;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(true);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(false);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+
+        assertTrue(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+    @Test
+    public void testShouldPeek_suppressedScreenOn_noDoze() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = false;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(true);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(false);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        assertFalse(mStatusBar.shouldPeek(entry, sbn));
+    }
+    @Test
+    public void testShouldPeek_suppressedScreenOff_dozing() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = true;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(true);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        assertFalse(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+    @Test
+    public void testShouldPeek_suppressedScreenOff_noDoze() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = false;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(true);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        assertTrue(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+
+    @Test
     public void testLogHidden() {
         try {
             mStatusBar.handleVisibleToUserChanged(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
new file mode 100644
index 0000000..6b20a1e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.volume;
+
+import android.media.MediaMetadata;
+import android.support.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+@SmallTest
+public class UtilTest extends SysuiTestCase {
+
+    @Test
+    public void testMediaMetadataToString_null() {
+        Assert.assertEquals(null, Util.mediaMetadataToString(null));
+    }
+
+    @Test
+    public void testMediaMetadataToString_notNull() {
+        Assert.assertNotNull(Util.mediaMetadataToString(new MediaMetadata.Builder().build()));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
new file mode 100644
index 0000000..8060f5b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.support.test.filters.SmallTest;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@SmallTest
+public class VolumeDialogControllerImplTest extends SysuiTestCase {
+
+    TestableVolumeDialogControllerImpl mVolumeController;
+    VolumeDialogControllerImpl.C mCallback;
+    StatusBar mStatusBar;
+
+    @Before
+    public void setup() throws Exception {
+        mCallback = mock(VolumeDialogControllerImpl.C.class);
+        mStatusBar = mock(StatusBar.class);
+        mVolumeController = new TestableVolumeDialogControllerImpl(mContext, mCallback, mStatusBar);
+    }
+
+    @Test
+    public void testVolumeChangeW_deviceNotInteractiveAOD() {
+        when(mStatusBar.isDeviceInteractive()).thenReturn(false);
+        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
+        verify(mCallback, never()).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
+    }
+
+    @Test
+    public void testVolumeChangeW_deviceInteractive() {
+        when(mStatusBar.isDeviceInteractive()).thenReturn(true);
+        mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI);
+        verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
+    }
+
+    static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl {
+        public TestableVolumeDialogControllerImpl(Context context, C callback, StatusBar s) {
+            super(context);
+            mCallbacks = callback;
+            mStatusBar = s;
+        }
+    }
+
+}
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index c760806..d118917 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -118,12 +118,9 @@
 import com.android.server.backup.utils.AppBackupUtils;
 import com.android.server.backup.utils.BackupManagerMonitorUtils;
 import com.android.server.backup.utils.BackupObserverUtils;
-import com.android.server.backup.utils.PasswordUtils;
 import com.android.server.backup.utils.SparseArrayUtils;
 import com.android.server.power.BatterySaverPolicy.ServiceType;
 
-import libcore.io.IoUtils;
-
 import com.google.android.collect.Sets;
 
 import java.io.BufferedInputStream;
@@ -802,8 +799,7 @@
 
         // Remember our ancestral dataset
         mTokenFile = new File(mBaseStateDir, "ancestral");
-        try {
-            RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r");
+        try (RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r")) {
             int version = tf.readInt();
             if (version == CURRENT_ANCESTRAL_RECORD_VERSION) {
                 mAncestralToken = tf.readLong();
@@ -818,7 +814,6 @@
                     }
                 }
             }
-            tf.close();
         } catch (FileNotFoundException fnf) {
             // Probably innocuous
             Slog.v(TAG, "No ancestral data");
@@ -842,13 +837,8 @@
         // If there are previous contents, parse them out then start a new
         // file to continue the recordkeeping.
         if (mEverStored.exists()) {
-            RandomAccessFile temp = null;
-            RandomAccessFile in = null;
-
-            try {
-                temp = new RandomAccessFile(tempProcessedFile, "rws");
-                in = new RandomAccessFile(mEverStored, "r");
-
+            try (RandomAccessFile temp = new RandomAccessFile(tempProcessedFile, "rws");
+                 RandomAccessFile in = new RandomAccessFile(mEverStored, "r")) {
                 // Loop until we hit EOF
                 while (true) {
                     String pkg = in.readUTF();
@@ -872,15 +862,6 @@
                 }
             } catch (IOException e) {
                 Slog.e(TAG, "Error in processed file", e);
-            } finally {
-                try {
-                    if (temp != null) temp.close();
-                } catch (IOException e) {
-                }
-                try {
-                    if (in != null) in.close();
-                } catch (IOException e) {
-                }
             }
         }
 
@@ -911,14 +892,9 @@
                 PackageManagerBackupAgent.getStorableApplications(mPackageManager);
 
         if (mFullBackupScheduleFile.exists()) {
-            FileInputStream fstream = null;
-            BufferedInputStream bufStream = null;
-            DataInputStream in = null;
-            try {
-                fstream = new FileInputStream(mFullBackupScheduleFile);
-                bufStream = new BufferedInputStream(fstream);
-                in = new DataInputStream(bufStream);
-
+            try (FileInputStream fstream = new FileInputStream(mFullBackupScheduleFile);
+                 BufferedInputStream bufStream = new BufferedInputStream(fstream);
+                 DataInputStream in = new DataInputStream(bufStream)) {
                 int version = in.readInt();
                 if (version != SCHEDULE_FILE_VERSION) {
                     Slog.e(TAG, "Unknown backup schedule version " + version);
@@ -979,10 +955,6 @@
                 Slog.e(TAG, "Unable to read backup schedule", e);
                 mFullBackupScheduleFile.delete();
                 schedule = null;
-            } finally {
-                IoUtils.closeQuietly(in);
-                IoUtils.closeQuietly(bufStream);
-                IoUtils.closeQuietly(fstream);
             }
         }
 
@@ -1443,18 +1415,11 @@
         synchronized (mEverStoredApps) {
             if (!mEverStoredApps.add(packageName)) return;
 
-            RandomAccessFile out = null;
-            try {
-                out = new RandomAccessFile(mEverStored, "rws");
+            try (RandomAccessFile out = new RandomAccessFile(mEverStored, "rws")) {
                 out.seek(out.length());
                 out.writeUTF(packageName);
             } catch (IOException e) {
                 Slog.e(TAG, "Can't log backup of " + packageName + " to " + mEverStored);
-            } finally {
-                try {
-                    if (out != null) out.close();
-                } catch (IOException e) {
-                }
             }
         }
     }
@@ -1469,16 +1434,13 @@
             // we'll recognize on initialization time that the package no longer
             // exists and fix it up then.
             File tempKnownFile = new File(mBaseStateDir, "processed.new");
-            RandomAccessFile known = null;
-            try {
-                known = new RandomAccessFile(tempKnownFile, "rws");
+            try (RandomAccessFile known = new RandomAccessFile(tempKnownFile, "rws")) {
                 mEverStoredApps.remove(packageName);
                 for (String s : mEverStoredApps) {
                     known.writeUTF(s);
                     if (MORE_DEBUG) Slog.v(TAG, "    " + s);
                 }
                 known.close();
-                known = null;
                 if (!tempKnownFile.renameTo(mEverStored)) {
                     throw new IOException("Can't rename " + tempKnownFile + " to " + mEverStored);
                 }
@@ -1491,11 +1453,6 @@
                 mEverStoredApps.clear();
                 tempKnownFile.delete();
                 mEverStored.delete();
-            } finally {
-                try {
-                    if (known != null) known.close();
-                } catch (IOException e) {
-                }
             }
         }
     }
@@ -1504,9 +1461,7 @@
     // as the set of packages with data [supposedly] available in the
     // ancestral dataset.
     public void writeRestoreTokens() {
-        try {
-            RandomAccessFile af = new RandomAccessFile(mTokenFile, "rwd");
-
+        try (RandomAccessFile af = new RandomAccessFile(mTokenFile, "rwd")) {
             // First, the version number of this record, for futureproofing
             af.writeInt(CURRENT_ANCESTRAL_RECORD_VERSION);
 
@@ -1525,7 +1480,6 @@
                     if (MORE_DEBUG) Slog.v(TAG, "   " + pkgName);
                 }
             }
-            af.close();
         } catch (IOException e) {
             Slog.w(TAG, "Unable to write token file:", e);
         }
@@ -2770,9 +2724,7 @@
         File base = new File(Environment.getDataDirectory(), "backup");
         File enableFile = new File(base, BACKUP_ENABLE_FILE);
         File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
-        FileOutputStream fout = null;
-        try {
-            fout = new FileOutputStream(stage);
+        try (FileOutputStream fout = new FileOutputStream(stage)) {
             fout.write(enable ? 1 : 0);
             fout.close();
             stage.renameTo(enableFile);
@@ -2788,8 +2740,6 @@
                     Settings.Secure.BACKUP_ENABLED, null, userId);
             enableFile.delete();
             stage.delete();
-        } finally {
-            IoUtils.closeQuietly(fout);
         }
     }
 
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index b88bbc1..2f9b861 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -206,7 +206,11 @@
 
         T get(int key) {
             T val = mArray.get(key);
-            val.checkOwnerOrSystemAndThrow();
+            // The value should never be null unless the resource doesn't exist
+            // (since we do not allow null resources to be added).
+            if (val != null) {
+                val.checkOwnerOrSystemAndThrow();
+            }
             return val;
         }
 
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index c68e5d6..4733840 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -48,6 +48,7 @@
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
+import android.util.DebugUtils;
 import android.util.Slog;
 import android.view.InputDevice;
 import android.media.AudioAttributes;
@@ -60,10 +61,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.ListIterator;
 
 public class VibratorService extends IVibratorService.Stub
         implements InputManager.InputDeviceListener {
@@ -948,6 +946,21 @@
         }
 
         private int runVibrate() {
+            try {
+                final int zenMode = Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.ZEN_MODE);
+                if (zenMode != Settings.Global.ZEN_MODE_OFF) {
+                    try (PrintWriter pw = getOutPrintWriter();) {
+                        pw.print("Ignoring because device is on DND mode ");
+                        pw.println(DebugUtils.flagsToString(Settings.Global.class, "ZEN_MODE_",
+                                zenMode));
+                        return 0;
+                    }
+                }
+            } catch (SettingNotFoundException e) {
+                // ignore
+            }
+
             final long duration = Long.parseLong(getNextArgRequired());
             if (duration > MAX_VIBRATION_MS) {
                 throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
@@ -972,7 +985,8 @@
                 pw.println("    Prints this help text.");
                 pw.println("");
                 pw.println("  vibrate duration [description]");
-                pw.println("    Vibrates for duration milliseconds.");
+                pw.println("    Vibrates for duration milliseconds; ignored when device is on DND ");
+                pw.println("    (Do Not Disturb) mode.");
                 pw.println("");
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ff387a7..97be508 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6715,7 +6715,6 @@
             mActiveUids.put(proc.uid, uidRec);
             EventLogTags.writeAmUidRunning(uidRec.uid);
             noteUidProcessState(uidRec.uid, uidRec.curProcState);
-            enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
         }
         proc.uidRecord = uidRec;
 
@@ -22826,8 +22825,9 @@
         for (int i=mActiveUids.size()-1; i>=0; i--) {
             final UidRecord uidRec = mActiveUids.valueAt(i);
             int uidChange = UidRecord.CHANGE_PROCSTATE;
-            if (uidRec.setProcState != uidRec.curProcState
-                    || uidRec.setWhitelist != uidRec.curWhitelist) {
+            if (uidRec.curProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
+                    && (uidRec.setProcState != uidRec.curProcState
+                           || uidRec.setWhitelist != uidRec.curWhitelist)) {
                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                         "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
                         + " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist
@@ -22848,7 +22848,7 @@
                                     mConstants.BACKGROUND_SETTLE_TIME);
                         }
                     }
-                    if (!uidRec.setIdle) {
+                    if (uidRec.idle && !uidRec.setIdle) {
                         uidChange = UidRecord.CHANGE_IDLE;
                     }
                 } else {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 83eea98..9273b3c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -23,6 +23,7 @@
 import android.app.IActivityController;
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
+import android.app.IUidObserver;
 import android.app.ProfilerInfo;
 import android.app.WaitResult;
 import android.app.usage.ConfigurationStats;
@@ -184,6 +185,8 @@
                     return runMakeIdle(pw);
                 case "monitor":
                     return runMonitor(pw);
+                case "watch-uids":
+                    return runWatchUids(pw);
                 case "hang":
                     return runHang(pw);
                 case "restart":
@@ -1294,6 +1297,141 @@
         return 0;
     }
 
+    static final class MyUidObserver extends IUidObserver.Stub {
+        final IActivityManager mInterface;
+        final PrintWriter mPw;
+        final InputStream mInput;
+
+        static final int STATE_NORMAL = 0;
+
+        int mState;
+
+        MyUidObserver(IActivityManager iam, PrintWriter pw, InputStream input) {
+            mInterface = iam;
+            mPw = pw;
+            mInput = input;
+        }
+
+        @Override
+        public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException {
+            synchronized (this) {
+                mPw.print(uid);
+                mPw.print(" procstate ");
+                mPw.print(ProcessList.makeProcStateString(procState));
+                mPw.print(" seq ");
+                mPw.println(procStateSeq);
+                mPw.flush();
+            }
+        }
+
+        @Override
+        public void onUidGone(int uid, boolean disabled) throws RemoteException {
+            synchronized (this) {
+                mPw.print(uid);
+                mPw.print(" gone");
+                if (disabled) {
+                    mPw.print(" disabled");
+                }
+                mPw.println();
+                mPw.flush();
+            }
+        }
+
+        @Override
+        public void onUidActive(int uid) throws RemoteException {
+            synchronized (this) {
+                mPw.print(uid);
+                mPw.println(" active");
+                mPw.flush();
+            }
+        }
+
+        @Override
+        public void onUidIdle(int uid, boolean disabled) throws RemoteException {
+            synchronized (this) {
+                mPw.print(uid);
+                mPw.print(" idle");
+                if (disabled) {
+                    mPw.print(" disabled");
+                }
+                mPw.println();
+                mPw.flush();
+            }
+        }
+
+        @Override
+        public void onUidCachedChanged(int uid, boolean cached) throws RemoteException {
+            synchronized (this) {
+                mPw.print(uid);
+                mPw.println(cached ? " cached" : " uncached");
+                mPw.flush();
+            }
+        }
+
+        void printMessageForState() {
+            switch (mState) {
+                case STATE_NORMAL:
+                    mPw.println("Watching uid states...  available commands:");
+                    break;
+            }
+            mPw.println("(q)uit: finish watching");
+        }
+
+        void run() throws RemoteException {
+            try {
+                printMessageForState();
+                mPw.flush();
+
+                mInterface.registerUidObserver(this, ActivityManager.UID_OBSERVER_ACTIVE
+                        | ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_PROCSTATE
+                        | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_CACHED,
+                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
+                mState = STATE_NORMAL;
+
+                InputStreamReader converter = new InputStreamReader(mInput);
+                BufferedReader in = new BufferedReader(converter);
+                String line;
+
+                while ((line = in.readLine()) != null) {
+                    boolean addNewline = true;
+                    if (line.length() <= 0) {
+                        addNewline = false;
+                    } else if ("q".equals(line) || "quit".equals(line)) {
+                        break;
+                    } else {
+                        mPw.println("Invalid command: " + line);
+                    }
+
+                    synchronized (this) {
+                        if (addNewline) {
+                            mPw.println("");
+                        }
+                        printMessageForState();
+                        mPw.flush();
+                    }
+                }
+
+            } catch (IOException e) {
+                e.printStackTrace(mPw);
+                mPw.flush();
+            } finally {
+                mInterface.unregisterUidObserver(this);
+            }
+        }
+    }
+
+    int runWatchUids(PrintWriter pw) throws RemoteException {
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            getErrPrintWriter().println("Error: Unknown option: " + opt);
+            return -1;
+        }
+
+        MyUidObserver controller = new MyUidObserver(mInterface, pw, getRawInputStream());
+        controller.run();
+        return 0;
+    }
+
     int runHang(PrintWriter pw) throws RemoteException {
         String opt;
         boolean allowRestart = false;
@@ -2599,6 +2737,8 @@
             pw.println("  monitor [--gdb <port>]");
             pw.println("      Start monitoring for crashes or ANRs.");
             pw.println("      --gdb: start gdbserv on the given port at crash/ANR");
+            pw.println("  watch-uids [--gdb <port>]");
+            pw.println("      Start watching for and reporting uid state changes.");
             pw.println("  hang [--allow-restart]");
             pw.println("      Hang the system.");
             pw.println("      --allow-restart: allow watchdog to perform normal system restart");
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index 1f02ebf..07f04b1 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -76,7 +76,7 @@
         m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
         SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
 
-        mLogger.log("onStopJob() jobid=", params.getJobId(), " op=", op);
+        mLogger.log("onStartJob() jobid=", params.getJobId(), " op=", op);
 
         if (op == null) {
             Slog.e(TAG, "Got invalid job " + params.getJobId());
@@ -131,4 +131,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 601dd94..83bb17e 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -2516,6 +2516,7 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         StringBuilder s = new StringBuilder();
+        s.append("  mStarted=").append(mStarted).append('\n');
         s.append("  mFixInterval=").append(mFixInterval).append('\n');
         s.append("  mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
         s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 8d53447..a105c84 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1132,12 +1132,6 @@
             fixateNewestUserKeyAuth(userId);
             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
             notifyActivePasswordMetricsAvailable(null, userId);
-
-            if (mStorage.getPersistentDataBlock() != null
-                    && LockPatternUtils.userOwnsFrpCredential(mUserManager.getUserInfo(userId))) {
-                // If owner, write to persistent storage for FRP
-                mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, userId, 0, null);
-            }
             return;
         }
         if (credential == null) {
@@ -1190,12 +1184,6 @@
             // Refresh the auth token
             doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
-            if (mStorage.getPersistentDataBlock() != null
-                    && LockPatternUtils.userOwnsFrpCredential(mUserManager.getUserInfo(userId))) {
-                // If owner, write to persistent storage for FRP
-                mStorage.writePersistentDataBlock(PersistentData.TYPE_GATEKEEPER, userId,
-                        requestedQuality, willStore.toBytes());
-            }
         } else {
             throw new RemoteException("Failed to enroll " +
                     (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password"
@@ -1443,18 +1431,12 @@
             return response;
         }
 
-        final CredentialHash storedHash;
         if (userId == USER_FRP) {
-            PersistentData data = mStorage.readPersistentDataBlock();
-            if (data.type != PersistentData.TYPE_GATEKEEPER) {
-                Slog.wtf(TAG, "Expected PersistentData.TYPE_GATEKEEPER, but was: " + data.type);
-                return VerifyCredentialResponse.ERROR;
-            }
-            return verifyFrpCredential(credential, credentialType, data, progressCallback);
-        } else {
-            storedHash = mStorage.readCredentialHash(userId);
+            Slog.wtf(TAG, "Unexpected FRP credential type, should be SP based.");
+            return VerifyCredentialResponse.ERROR;
         }
 
+        final CredentialHash storedHash = mStorage.readCredentialHash(userId);
         if (storedHash.type != credentialType) {
             Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??"
                     + " stored: " + storedHash.type + " passed in: " + credentialType);
@@ -1485,29 +1467,6 @@
         return response;
     }
 
-    private VerifyCredentialResponse verifyFrpCredential(String credential, int credentialType,
-            PersistentData data, ICheckCredentialProgressCallback progressCallback)
-            throws RemoteException {
-        CredentialHash storedHash = CredentialHash.fromBytes(data.payload);
-        if (storedHash.type != credentialType) {
-            Slog.wtf(TAG, "doVerifyCredential type mismatch with stored credential??"
-                    + " stored: " + storedHash.type + " passed in: " + credentialType);
-            return VerifyCredentialResponse.ERROR;
-        }
-        if (ArrayUtils.isEmpty(storedHash.hash) || TextUtils.isEmpty(credential)) {
-            Slog.e(TAG, "Stored hash or credential is empty");
-            return VerifyCredentialResponse.ERROR;
-        }
-        VerifyCredentialResponse response = VerifyCredentialResponse.fromGateKeeperResponse(
-                getGateKeeperService().verifyChallenge(data.userId, 0 /* challenge */,
-                        storedHash.hash, credential.getBytes()));
-        if (progressCallback != null
-                && response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
-            progressCallback.onCredentialVerified();
-        }
-        return response;
-    }
-
     @Override
     public VerifyCredentialResponse verifyTiedProfileChallenge(String credential, int type,
             long challenge, int userId) throws RemoteException {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 79372e48..b4c10ec 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -635,9 +635,8 @@
         static final int VERSION_1_HEADER_SIZE = 1 + 1 + 4 + 4;
 
         public static final int TYPE_NONE = 0;
-        public static final int TYPE_GATEKEEPER = 1;
-        public static final int TYPE_SP = 2;
-        public static final int TYPE_SP_WEAVER = 3;
+        public static final int TYPE_SP = 1;
+        public static final int TYPE_SP_WEAVER = 2;
 
         public static final PersistentData NONE = new PersistentData(TYPE_NONE,
                 UserHandle.USER_NULL, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, null);
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index 1bd2085..184f8b2 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -47,9 +47,11 @@
         if (!userWantsBadges || !appCanShowBadge) {
             record.setShowBadge(false);
         } else {
-            record.setShowBadge(mConfig.getNotificationChannel(record.sbn.getPackageName(),
-                    record.sbn.getUid(), record.getChannel().getId(), false).canShowBadge()
-                    && appCanShowBadge);
+            if (record.getChannel() != null) {
+                record.setShowBadge(record.getChannel().canShowBadge() && appCanShowBadge);
+            } else {
+                record.setShowBadge(appCanShowBadge);
+            }
         }
 
         return null;
diff --git a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java
new file mode 100644
index 0000000..7c82845
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java
@@ -0,0 +1,48 @@
+/**
+* Copyright (C) 2017 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.android.server.notification;
+
+import android.content.Context;
+import android.util.Slog;
+
+/**
+ * Applies adjustments from the group helper and notification assistant
+ */
+public class NotificationAdjustmentExtractor implements NotificationSignalExtractor {
+    private static final String TAG = "BadgeExtractor";
+    private static final boolean DBG = false;
+
+
+    public void initialize(Context ctx, NotificationUsageStats usageStats) {
+        if (DBG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
+    }
+
+    public RankingReconsideration process(NotificationRecord record) {
+        if (record == null || record.getNotification() == null) {
+            if (DBG) Slog.d(TAG, "skipping empty notification");
+            return null;
+        }
+
+        record.applyAdjustments();
+
+        return null;
+    }
+
+    @Override
+    public void setConfig(RankingConfig config) {
+        // config is not used
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
new file mode 100644
index 0000000..46ab556
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
@@ -0,0 +1,55 @@
+/**
+* Copyright (C) 2017 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.android.server.notification;
+
+import android.content.Context;
+import android.util.Slog;
+
+/**
+ * Stores the latest notification channel information for this notification
+ */
+public class NotificationChannelExtractor implements NotificationSignalExtractor {
+    private static final String TAG = "BadgeExtractor";
+    private static final boolean DBG = false;
+
+    private RankingConfig mConfig;
+
+    public void initialize(Context ctx, NotificationUsageStats usageStats) {
+        if (DBG) Slog.d(TAG, "Initializing  " + getClass().getSimpleName() + ".");
+    }
+
+    public RankingReconsideration process(NotificationRecord record) {
+        if (record == null || record.getNotification() == null) {
+            if (DBG) Slog.d(TAG, "skipping empty notification");
+            return null;
+        }
+
+        if (mConfig == null) {
+            if (DBG) Slog.d(TAG, "missing config");
+            return null;
+        }
+
+        record.updateNotificationChannel(mConfig.getNotificationChannel(record.sbn.getPackageName(),
+                record.sbn.getUid(), record.getChannel().getId(), false));
+
+        return null;
+    }
+
+    @Override
+    public void setConfig(RankingConfig config) {
+        mConfig = config;
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index 4981d5c..12b29cf 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -58,6 +58,10 @@
             }
         }
 
+        if (!record.isRecentlyIntrusive()) {
+            return null;
+        }
+
         return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
             @Override
             public void work() {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c0f9e0d..c816e7f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -278,7 +278,7 @@
     private ICompanionDeviceManager mCompanionManager;
 
     final IBinder mForegroundToken = new Binder();
-    private Handler mHandler;
+    private WorkerHandler mHandler;
     private final HandlerThread mRankingThread = new HandlerThread("ranker",
             Process.THREAD_PRIORITY_BACKGROUND);
 
@@ -295,8 +295,8 @@
     private String mVibrateNotificationKey;
 
     private final SparseArray<ArraySet<ManagedServiceInfo>> mListenersDisablingEffects =
-            new SparseArray<ArraySet<ManagedServiceInfo>>();
-    private List<ComponentName> mEffectsSuppressors = new ArrayList<ComponentName>();
+            new SparseArray<>();
+    private List<ComponentName> mEffectsSuppressors = new ArrayList<>();
     private int mListenerHints;  // right now, all hints are global
     private int mInterruptionFilter = NotificationListenerService.INTERRUPTION_FILTER_UNKNOWN;
 
@@ -312,16 +312,14 @@
     // used as a mutex for access to all active notifications & listeners
     final Object mNotificationLock = new Object();
     @GuardedBy("mNotificationLock")
-    final ArrayList<NotificationRecord> mNotificationList =
-            new ArrayList<NotificationRecord>();
+    final ArrayList<NotificationRecord> mNotificationList = new ArrayList<>();
     @GuardedBy("mNotificationLock")
-    final ArrayMap<String, NotificationRecord> mNotificationsByKey =
-            new ArrayMap<String, NotificationRecord>();
+    final ArrayMap<String, NotificationRecord> mNotificationsByKey = new ArrayMap<>();
     @GuardedBy("mNotificationLock")
     final ArrayList<NotificationRecord> mEnqueuedNotifications = new ArrayList<>();
     @GuardedBy("mNotificationLock")
     final ArrayMap<Integer, ArrayMap<String, String>> mAutobundledSummaries = new ArrayMap<>();
-    final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
+    final ArrayList<ToastRecord> mToastQueue = new ArrayList<>();
     final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
 
     // The last key in this list owns the hardware.
@@ -1093,7 +1091,7 @@
                     count--;
                 }
                 if (posted.sbn.isGroup() && posted.getNotification().isGroupSummary()) {
-                    count --;
+                    count--;
                 }
             }
 
@@ -1101,6 +1099,13 @@
         }
     }
 
+    void clearNotifications() {
+        mEnqueuedNotifications.clear();
+        mNotificationList.clear();
+        mNotificationsByKey.clear();
+        mSummaryByGroupKey.clear();
+    }
+
     @VisibleForTesting
     void addNotification(NotificationRecord r) {
         mNotificationList.add(r);
@@ -1121,7 +1126,7 @@
     }
 
     @VisibleForTesting
-    void setHandler(Handler handler) {
+    void setHandler(WorkerHandler handler) {
         mHandler = handler;
     }
 
@@ -1141,6 +1146,11 @@
     }
 
     @VisibleForTesting
+    void setRankingHandler(RankingHandler rankingHandler) {
+        mRankingHandler = rankingHandler;
+    }
+
+    @VisibleForTesting
     void setIsTelevision(boolean isTelevision) {
         mIsTelevision = isTelevision;
     }
@@ -1152,7 +1162,8 @@
 
     // TODO: Tests should call onStart instead once the methods above are removed.
     @VisibleForTesting
-    void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
+    void init(Looper looper, IPackageManager packageManager,
+            PackageManager packageManagerClient,
             LightsManager lightsManager, NotificationListeners notificationListeners,
             NotificationAssistants notificationAssistants, ConditionProviders conditionProviders,
             ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
@@ -1323,7 +1334,8 @@
 
         final File systemDir = new File(Environment.getDataDirectory(), "system");
 
-        init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
+        init(Looper.myLooper(),
+                AppGlobals.getPackageManager(), getContext().getPackageManager(),
                 getLocalService(LightsManager.class),
                 new NotificationListeners(AppGlobals.getPackageManager()),
                 new NotificationAssistants(AppGlobals.getPackageManager()),
@@ -1343,7 +1355,6 @@
                 synchronized (mNotificationLock) {
                     addAutogroupKeyLocked(key);
                 }
-                mRankingHandler.requestSort(false);
             }
 
             @Override
@@ -1351,7 +1362,6 @@
                 synchronized (mNotificationLock) {
                     removeAutogroupKeyLocked(key);
                 }
-                mRankingHandler.requestSort(false);
             }
 
             @Override
@@ -1424,28 +1434,14 @@
         }
         mRankingHelper.updateNotificationChannel(pkg, uid, channel);
 
-        final NotificationChannel modifiedChannel =
-                mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
-
         if (!fromListener) {
+            final NotificationChannel modifiedChannel =
+                    mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
             mListeners.notifyNotificationChannelChanged(
                     pkg, UserHandle.getUserHandleForUid(uid),
                     modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
         }
 
-        synchronized (mNotificationLock) {
-            final int N = mNotificationList.size();
-            for (int i = N - 1; i >= 0; --i) {
-                NotificationRecord r = mNotificationList.get(i);
-                if (r.sbn.getPackageName().equals(pkg)
-                        && r.sbn.getUid() == uid
-                        && channel.getId() != null
-                        && channel.getId().equals(r.getChannel().getId())) {
-                    r.updateNotificationChannel(modifiedChannel);
-                }
-            }
-        }
-        mRankingHandler.requestSort(true);
         savePolicyFile();
     }
 
@@ -2883,7 +2879,7 @@
                     NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
                     applyAdjustment(n, adjustment);
                 }
-                mRankingHandler.requestSort(true);
+                mRankingHandler.requestSort();
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2902,7 +2898,7 @@
                         applyAdjustment(n, adjustment);
                     }
                 }
-                mRankingHandler.requestSort(true);
+                mRankingHandler.requestSort();
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2976,39 +2972,44 @@
         }
     };
 
-    private void applyAdjustment(NotificationRecord n, Adjustment adjustment) {
-        if (n == null) {
+    private void applyAdjustment(NotificationRecord r, Adjustment adjustment) {
+        if (r == null) {
             return;
         }
         if (adjustment.getSignals() != null) {
             Bundle.setDefusable(adjustment.getSignals(), true);
-            final ArrayList<String> people =
-                    adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE);
-            final ArrayList<SnoozeCriterion> snoozeCriterionList =
-                    adjustment.getSignals().getParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA);
-            n.setPeopleOverride(people);
-            n.setSnoozeCriteria(snoozeCriterionList);
+            r.addAdjustment(adjustment);
         }
     }
 
     @GuardedBy("mNotificationLock")
-    private void addAutogroupKeyLocked(String key) {
-        NotificationRecord n = mNotificationsByKey.get(key);
-        if (n == null) {
+    void addAutogroupKeyLocked(String key) {
+        NotificationRecord r = mNotificationsByKey.get(key);
+        if (r == null) {
             return;
         }
-        n.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
+        addAutoGroupAdjustment(r, GroupHelper.AUTOGROUP_KEY);
         EventLogTags.writeNotificationAutogrouped(key);
+        mRankingHandler.requestSort();
     }
 
     @GuardedBy("mNotificationLock")
-    private void removeAutogroupKeyLocked(String key) {
-        NotificationRecord n = mNotificationsByKey.get(key);
-        if (n == null) {
+    void removeAutogroupKeyLocked(String key) {
+        NotificationRecord r = mNotificationsByKey.get(key);
+        if (r == null) {
             return;
         }
-        n.setOverrideGroupKey(null);
+        addAutoGroupAdjustment(r, null);
         EventLogTags.writeNotificationUnautogrouped(key);
+        mRankingHandler.requestSort();
+    }
+
+    private void addAutoGroupAdjustment(NotificationRecord r, String overrideGroupKey) {
+        Bundle signals = new Bundle();
+        signals.putString(Adjustment.KEY_GROUP_KEY, overrideGroupKey);
+        Adjustment adjustment =
+                new Adjustment(r.sbn.getPackageName(), r.getKey(), signals, "", r.sbn.getUserId());
+        r.addAdjustment(adjustment);
     }
 
     // Clears the 'fake' auto-group summary.
@@ -4267,39 +4268,44 @@
             }
         }
         if (changed) {
-            scheduleSendRankingUpdate();
+            mHandler.scheduleSendRankingUpdate();
         }
     }
 
-    private void handleRankingSort(Message msg) {
-        if (!(msg.obj instanceof Boolean)) return;
+    void handleRankingSort() {
         if (mRankingHelper == null) return;
-        boolean forceUpdate = ((Boolean) msg.obj == null) ? false : (boolean) msg.obj;
         synchronized (mNotificationLock) {
             final int N = mNotificationList.size();
-            // Any field that can change via one of the extractors or by the assistant
-            // needs to be added here.
-            ArrayList<String> orderBefore = new ArrayList<String>(N);
-            ArrayList<String> groupOverrideBefore = new ArrayList<>(N);
+            // Any field that can change via one of the extractors needs to be added here.
+            ArrayList<String> orderBefore = new ArrayList<>(N);
             int[] visibilities = new int[N];
             boolean[] showBadges = new boolean[N];
+            ArrayList<NotificationChannel> channelBefore = new ArrayList<>(N);
+            ArrayList<String> groupKeyBefore = new ArrayList<>(N);
+            ArrayList<ArrayList<String>> overridePeopleBefore = new ArrayList<>(N);
+            ArrayList<ArrayList<SnoozeCriterion>> snoozeCriteriaBefore = new ArrayList<>(N);
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
                 orderBefore.add(r.getKey());
-                groupOverrideBefore.add(r.sbn.getGroupKey());
                 visibilities[i] = r.getPackageVisibilityOverride();
                 showBadges[i] = r.canShowBadge();
+                channelBefore.add(r.getChannel());
+                groupKeyBefore.add(r.getGroupKey());
+                overridePeopleBefore.add(r.getPeopleOverride());
+                snoozeCriteriaBefore.add(r.getSnoozeCriteria());
                 mRankingHelper.extractSignals(r);
             }
             mRankingHelper.sort(mNotificationList);
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
-                if (forceUpdate
-                        || !orderBefore.get(i).equals(r.getKey())
+                if (!orderBefore.get(i).equals(r.getKey())
                         || visibilities[i] != r.getPackageVisibilityOverride()
-                        || !groupOverrideBefore.get(i).equals(r.sbn.getGroupKey())
-                        || showBadges[i] != r.canShowBadge()) {
-                    scheduleSendRankingUpdate();
+                        || showBadges[i] != r.canShowBadge()
+                        || !Objects.equals(channelBefore.get(i), r.getChannel())
+                        || !Objects.equals(groupKeyBefore.get(i), r.getGroupKey())
+                        || !Objects.equals(overridePeopleBefore.get(i), r.getPeopleOverride())
+                        || !Objects.equals(snoozeCriteriaBefore.get(i), r.getSnoozeCriteria())) {
+                    mHandler.scheduleSendRankingUpdate();
                     return;
                 }
             }
@@ -4333,13 +4339,6 @@
         return mRankingHelper.indexOf(mNotificationList, target);
     }
 
-    private void scheduleSendRankingUpdate() {
-        if (!mHandler.hasMessages(MESSAGE_SEND_RANKING_UPDATE)) {
-            Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE);
-            mHandler.sendMessage(m);
-        }
-    }
-
     private void handleSendRankingUpdate() {
         synchronized (mNotificationLock) {
             mListeners.notifyRankingUpdateLocked();
@@ -4371,7 +4370,7 @@
         }
     }
 
-    private final class WorkerHandler extends Handler
+    protected class WorkerHandler extends Handler
     {
         public WorkerHandler(Looper looper) {
             super(looper);
@@ -4400,6 +4399,13 @@
             }
         }
 
+        protected void scheduleSendRankingUpdate() {
+            if (!hasMessages(MESSAGE_SEND_RANKING_UPDATE)) {
+                Message m = Message.obtain(this, MESSAGE_SEND_RANKING_UPDATE);
+                sendMessage(m);
+            }
+        }
+
     }
 
     private final class RankingHandlerWorker extends Handler implements RankingHandler
@@ -4415,16 +4421,15 @@
                     handleRankingReconsideration(msg);
                     break;
                 case MESSAGE_RANKING_SORT:
-                    handleRankingSort(msg);
+                    handleRankingSort();
                     break;
             }
         }
 
-        public void requestSort(boolean forceUpdate) {
+        public void requestSort() {
             removeMessages(MESSAGE_RANKING_SORT);
             Message msg = Message.obtain();
             msg.what = MESSAGE_RANKING_SORT;
-            msg.obj = forceUpdate;
             sendMessage(msg);
         }
 
@@ -5741,6 +5746,8 @@
         public static final String USAGE = "help\n"
                 + "allow_listener COMPONENT\n"
                 + "disallow_listener COMPONENT\n"
+                + "set_assistant COMPONENT\n"
+                + "remove_assistant COMPONENT\n"
                 + "allow_dnd PACKAGE\n"
                 + "disallow_dnd PACKAGE";
 
@@ -5781,6 +5788,24 @@
                         getBinderService().setNotificationListenerAccessGranted(cn, false);
                     }
                     break;
+                    case "allow_assistant": {
+                        ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
+                        if (cn == null) {
+                            pw.println("Invalid assistant - must be a ComponentName");
+                            return -1;
+                        }
+                        getBinderService().setNotificationAssistantAccessGranted(cn, true);
+                    }
+                    break;
+                    case "disallow_assistant": {
+                        ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
+                        if (cn == null) {
+                            pw.println("Invalid assistant - must be a ComponentName");
+                            return -1;
+                        }
+                        getBinderService().setNotificationAssistantAccessGranted(cn, false);
+                    }
+                    break;
 
                     default:
                         return handleDefaultCommands(cmd);
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 1dee71c..77bf9e3 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -35,8 +35,10 @@
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.notification.Adjustment;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRecordProto;
 import android.service.notification.SnoozeCriterion;
@@ -57,6 +59,7 @@
 import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -132,6 +135,8 @@
     private String mGroupLogTag;
     private String mChannelIdLogTag;
 
+    private final List<Adjustment> mAdjustments;
+
     @VisibleForTesting
     public NotificationRecord(Context context, StatusBarNotification sbn,
             NotificationChannel channel)
@@ -150,6 +155,7 @@
         mAttributes = calculateAttributes();
         mImportance = calculateImportance();
         mLight = calculateLights();
+        mAdjustments = new ArrayList<>();
     }
 
     private boolean isPreChannelsNotification() {
@@ -504,6 +510,7 @@
         if (getSnoozeCriteria() != null) {
             pw.println(prefix + "snoozeCriteria=" + TextUtils.join(",", getSnoozeCriteria()));
         }
+        pw.println(prefix + "mAdjustments=" + mAdjustments);
     }
 
 
@@ -539,6 +546,36 @@
                 this.sbn.getNotification());
     }
 
+    public void addAdjustment(Adjustment adjustment) {
+        synchronized (mAdjustments) {
+            mAdjustments.add(adjustment);
+        }
+    }
+
+    public void applyAdjustments() {
+        synchronized (mAdjustments) {
+            for (Adjustment adjustment: mAdjustments) {
+                Bundle signals = adjustment.getSignals();
+                if (signals.containsKey(Adjustment.KEY_PEOPLE)) {
+                    final ArrayList<String> people =
+                            adjustment.getSignals().getStringArrayList(Adjustment.KEY_PEOPLE);
+                    setPeopleOverride(people);
+                }
+                if (signals.containsKey(Adjustment.KEY_SNOOZE_CRITERIA)) {
+                    final ArrayList<SnoozeCriterion> snoozeCriterionList =
+                            adjustment.getSignals().getParcelableArrayList(
+                                    Adjustment.KEY_SNOOZE_CRITERIA);
+                    setSnoozeCriteria(snoozeCriterionList);
+                }
+                if (signals.containsKey(Adjustment.KEY_GROUP_KEY)) {
+                    final String groupOverrideKey =
+                            adjustment.getSignals().getString(Adjustment.KEY_GROUP_KEY);
+                    setOverrideGroupKey(groupOverrideKey);
+                }
+            }
+        }
+    }
+
     public void setContactAffinity(float contactAffinity) {
         mContactAffinity = contactAffinity;
         if (mImportance < IMPORTANCE_DEFAULT &&
diff --git a/services/core/java/com/android/server/notification/RankingHandler.java b/services/core/java/com/android/server/notification/RankingHandler.java
index 656d727..96324d8 100644
--- a/services/core/java/com/android/server/notification/RankingHandler.java
+++ b/services/core/java/com/android/server/notification/RankingHandler.java
@@ -16,6 +16,6 @@
 package com.android.server.notification;
 
 public interface RankingHandler {
-    public void requestSort(boolean forceUpdate);
+    public void requestSort();
     public void requestReconsideration(RankingReconsideration recon);
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 108a41d..5c2c2b3 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -399,7 +399,7 @@
         for (int i = 0; i < N; i++) {
             mSignalExtractors[i].setConfig(this);
         }
-        mRankingHandler.requestSort(false);
+        mRankingHandler.requestSort();
     }
 
     public void sort(ArrayList<NotificationRecord> notificationList) {
@@ -511,7 +511,6 @@
             MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
         }
         r.groups.put(group.getId(), group);
-        updateConfig();
     }
 
     @Override
@@ -569,7 +568,6 @@
         r.channels.put(channel.getId(), channel);
         MetricsLogger.action(getChannelLog(channel, pkg).setType(
                 MetricsProto.MetricsEvent.TYPE_OPEN));
-        updateConfig();
     }
 
     void clearLockedFields(NotificationChannel channel) {
@@ -641,7 +639,6 @@
             LogMaker lm = getChannelLog(channel, pkg);
             lm.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
             MetricsLogger.action(lm);
-            updateConfig();
         }
     }
 
@@ -655,7 +652,6 @@
             return;
         }
         r.channels.remove(channelId);
-        updateConfig();
     }
 
     @Override
@@ -672,7 +668,6 @@
                 r.channels.remove(key);
             }
         }
-        updateConfig();
     }
 
     public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
@@ -735,7 +730,6 @@
                 deletedChannels.add(nc);
             }
         }
-        updateConfig();
         return deletedChannels;
     }
 
@@ -1150,7 +1144,7 @@
             changed |= oldValue != newValue;
         }
         if (changed) {
-            mRankingHandler.requestSort(false);
+            mRankingHandler.requestSort();
         }
     }
 
diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
index fe82dc4..cac7f7b 100644
--- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java
+++ b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
@@ -16,6 +16,7 @@
 
 package com.android.server.timezone;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.FastXmlSerializer;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -80,7 +81,7 @@
     private final AtomicFile mPackageStatusFile;
 
     PackageStatusStorage(File storageDir) {
-        mPackageStatusFile = new AtomicFile(new File(storageDir, "packageStatus.xml"));
+        mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"));
         if (!mPackageStatusFile.getBaseFile().exists()) {
             try {
                 insertInitialPackageStatus();
@@ -103,7 +104,7 @@
     PackageStatus getPackageStatus() {
         synchronized (this) {
             try {
-                return getPackageStatusInternal();
+                return getPackageStatusLocked();
             } catch (ParseException e) {
                 // This means that data exists in the file but it was bad.
                 Slog.e(LOG_TAG, "Package status invalid, resetting and retrying", e);
@@ -111,7 +112,7 @@
                 // Reset the storage so it is in a good state again.
                 recoverFromBadData(e);
                 try {
-                    return getPackageStatusInternal();
+                    return getPackageStatusLocked();
                 } catch (ParseException e2) {
                     throw new IllegalStateException("Recovery from bad file failed", e2);
                 }
@@ -119,7 +120,8 @@
         }
     }
 
-    private PackageStatus getPackageStatusInternal() throws ParseException {
+    @GuardedBy("this")
+    private PackageStatus getPackageStatusLocked() throws ParseException {
         try (FileInputStream fis = mPackageStatusFile.openRead()) {
             XmlPullParser parser = parseToPackageStatusTag(fis);
             Integer checkStatus = getNullableIntAttribute(parser, ATTRIBUTE_CHECK_STATUS);
@@ -137,7 +139,7 @@
         }
     }
 
-    // Callers should be synchronized(this).
+    @GuardedBy("this")
     private int recoverFromBadData(Exception cause) {
         mPackageStatusFile.delete();
         try {
@@ -155,7 +157,7 @@
         // is reset to ensure that old tokens are unlikely to work.
         final int initialOptimisticLockId = (int) System.currentTimeMillis();
 
-        writePackageStatusInternal(null /* status */, initialOptimisticLockId,
+        writePackageStatusLocked(null /* status */, initialOptimisticLockId,
                 null /* packageVersions */);
         return initialOptimisticLockId;
     }
@@ -243,7 +245,7 @@
         }
     }
 
-    // Caller should be synchronized(this).
+    @GuardedBy("this")
     private int getCurrentOptimisticLockId() throws ParseException {
         try (FileInputStream fis = mPackageStatusFile.openRead()) {
             XmlPullParser parser = parseToPackageStatusTag(fis);
@@ -278,7 +280,7 @@
         }
     }
 
-    // Caller should be synchronized(this).
+    @GuardedBy("this")
     private boolean writePackageStatusWithOptimisticLockCheck(int optimisticLockId,
             int newOptimisticLockId, Integer status, PackageVersions packageVersions)
             throws IOException {
@@ -294,12 +296,12 @@
             return false;
         }
 
-        writePackageStatusInternal(status, newOptimisticLockId, packageVersions);
+        writePackageStatusLocked(status, newOptimisticLockId, packageVersions);
         return true;
     }
 
-    // Caller should be synchronized(this).
-    private void writePackageStatusInternal(Integer status, int optimisticLockId,
+    @GuardedBy("this")
+    private void writePackageStatusLocked(Integer status, int optimisticLockId,
             PackageVersions packageVersions) throws IOException {
         if ((status == null) != (packageVersions == null)) {
             throw new IllegalArgumentException(
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index edd7d53..4fb2ae3 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1523,6 +1523,10 @@
                           << " satellites:: " << std::endl;
         }
 
+        internalState << "constellation: 1=GPS, 2=SBAS, 3=GLO, 4=QZSS, 5=BDS, 6=GAL; "
+                      << "ephemerisType: 0=Eph, 1=Alm, 2=?; "
+                      << "ephemerisSource: 0=Demod, 1=Supl, 2=Server, 3=?; "
+                      << "ephemerisHealth: 0=Good, 1=Bad, 2=?" << std::endl;
         for (size_t i = 0; i < data.satelliteDataArray.size(); i++) {
             internalState << "svid: " << data.satelliteDataArray[i].svid
                           << ", constellation: "
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 070b808..2db7dbe 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -64,7 +64,7 @@
 static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
 
 // Throttling interval for user activity calls.
-static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 500 * 1000000L; // 500ms
+static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 100 * 1000000L; // 100ms
 
 // ----------------------------------------------------------------------------
 
@@ -104,19 +104,6 @@
 }
 
 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
-    // Tell the power HAL when user activity occurs.
-    gPowerHalMutex.lock();
-    if (getPowerHal()) {
-        Return<void> ret;
-        if (gPowerHalV1_1 != nullptr) {
-            ret = gPowerHalV1_1->powerHintAsync(PowerHint::INTERACTION, 0);
-        } else {
-            ret = gPowerHalV1_0->powerHint(PowerHint::INTERACTION, 0);
-        }
-        processReturn(ret, "powerHint");
-    }
-    gPowerHalMutex.unlock();
-
     if (gPowerManagerServiceObj) {
         // Throttle calls into user activity by event type.
         // We're a little conservative about argument checking here in case the caller
@@ -131,6 +118,21 @@
                 return;
             }
             gLastEventTime[eventType] = eventTime;
+
+
+            // Tell the power HAL when user activity occurs.
+            gPowerHalMutex.lock();
+            if (getPowerHal()) {
+              Return<void> ret;
+              if (gPowerHalV1_1 != nullptr) {
+                ret = gPowerHalV1_1->powerHintAsync(PowerHint::INTERACTION, 0);
+              } else {
+                ret = gPowerHalV1_0->powerHint(PowerHint::INTERACTION, 0);
+              }
+              processReturn(ret, "powerHint");
+            }
+            gPowerHalMutex.unlock();
+
         }
 
         JNIEnv* env = AndroidRuntime::getJNIEnv();
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 3ec8380..6c417a9 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -263,6 +263,8 @@
             Preconditions.checkFlagsArgument(selectionFlags,
                     PrintManager.DISABLED_SERVICES | PrintManager.ENABLED_SERVICES);
 
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRINT_SERVICES, null);
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -316,6 +318,8 @@
 
         @Override
         public List<RecommendationInfo> getPrintServiceRecommendations(int userId) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS, null);
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -538,6 +542,8 @@
                 int userId) throws RemoteException {
             listener = Preconditions.checkNotNull(listener);
 
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRINT_SERVICES,
+                    null);
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -560,6 +566,8 @@
                 int userId) {
             listener = Preconditions.checkNotNull(listener);
 
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRINT_SERVICES,
+                    null);
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -583,6 +591,8 @@
                 throws RemoteException {
             listener = Preconditions.checkNotNull(listener);
 
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS, null);
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -605,6 +615,8 @@
                 IRecommendationsChangeListener listener, int userId) {
             listener = Preconditions.checkNotNull(listener);
 
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS, null);
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
             final UserState userState;
             synchronized (mLock) {
@@ -888,12 +900,12 @@
 
         private int resolveCallingAppEnforcingPermissions(int appId) {
             final int callingUid = Binder.getCallingUid();
-            if (callingUid == 0 || callingUid == Process.SYSTEM_UID
-                    || callingUid == Process.SHELL_UID) {
+            if (callingUid == 0) {
                 return appId;
             }
             final int callingAppId = UserHandle.getAppId(callingUid);
-            if (appId == callingAppId) {
+            if (appId == callingAppId || callingAppId == Process.SHELL_UID
+                    || callingAppId == Process.SYSTEM_UID) {
                 return appId;
             }
             if (mContext.checkCallingPermission(
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 807703b..f7d2a02 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -76,7 +76,8 @@
     @Mock Vibrator mVibrator;
     @Mock android.media.IRingtonePlayer mRingtonePlayer;
     @Mock Light mLight;
-    @Mock Handler mHandler;
+    @Mock
+    NotificationManagerService.WorkerHandler mHandler;
     @Mock
     NotificationUsageStats mUsageStats;
 
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
new file mode 100644
index 0000000..e527644
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.service.notification.Adjustment;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+public class NotificationAdjustmentExtractorTest extends NotificationTestCase {
+
+    @Test
+    public void testExtractsAdjustment() {
+        NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor();
+
+        NotificationRecord r = generateRecord();
+
+        Bundle signals = new Bundle();
+        signals.putString(Adjustment.KEY_GROUP_KEY, GroupHelper.AUTOGROUP_KEY);
+        ArrayList<SnoozeCriterion> snoozeCriteria = new ArrayList<>();
+        snoozeCriteria.add(new SnoozeCriterion("n", "n", "n"));
+        signals.putParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA, snoozeCriteria);
+        ArrayList<String> people = new ArrayList<>();
+        people.add("you");
+        signals.putStringArrayList(Adjustment.KEY_PEOPLE, people);
+        Adjustment adjustment = new Adjustment("pkg", r.getKey(), signals, "", 0);
+        r.addAdjustment(adjustment);
+
+        assertFalse(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
+        assertFalse(Objects.equals(people, r.getPeopleOverride()));
+        assertFalse(Objects.equals(snoozeCriteria, r.getSnoozeCriteria()));
+
+        assertNull(extractor.process(r));
+
+        assertTrue(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
+        assertEquals(people, r.getPeopleOverride());
+        assertEquals(snoozeCriteria, r.getSnoozeCriteria());
+    }
+
+    @Test
+    public void testExtractsAdjustments() {
+        NotificationAdjustmentExtractor extractor = new NotificationAdjustmentExtractor();
+
+        NotificationRecord r = generateRecord();
+
+        Bundle pSignals = new Bundle();
+        ArrayList<String> people = new ArrayList<>();
+        people.add("you");
+        pSignals.putStringArrayList(Adjustment.KEY_PEOPLE, people);
+        Adjustment pAdjustment = new Adjustment("pkg", r.getKey(), pSignals, "", 0);
+        r.addAdjustment(pAdjustment);
+
+        Bundle sSignals = new Bundle();
+        ArrayList<SnoozeCriterion> snoozeCriteria = new ArrayList<>();
+        snoozeCriteria.add(new SnoozeCriterion("n", "n", "n"));
+        sSignals.putParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA, snoozeCriteria);
+        Adjustment sAdjustment = new Adjustment("pkg", r.getKey(), sSignals, "", 0);
+        r.addAdjustment(sAdjustment);
+
+        Bundle gSignals = new Bundle();
+        gSignals.putString(Adjustment.KEY_GROUP_KEY, GroupHelper.AUTOGROUP_KEY);
+        Adjustment gAdjustment = new Adjustment("pkg", r.getKey(), gSignals, "", 0);
+        r.addAdjustment(gAdjustment);
+
+        assertFalse(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
+        assertFalse(Objects.equals(people, r.getPeopleOverride()));
+        assertFalse(Objects.equals(snoozeCriteria, r.getSnoozeCriteria()));
+
+        assertNull(extractor.process(r));
+
+        assertTrue(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
+        assertEquals(people, r.getPeopleOverride());
+        assertEquals(snoozeCriteria, r.getSnoozeCriteria());
+    }
+
+    private NotificationRecord generateRecord() {
+        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+        final Notification.Builder builder = new Notification.Builder(getContext())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+        Notification n = builder.build();
+        StatusBarNotification sbn = new StatusBarNotification("", "", 0, "", 0,
+                0, n, UserHandle.ALL, null, System.currentTimeMillis());
+       return new NotificationRecord(getContext(), sbn, channel);
+    }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationChannelExtractorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationChannelExtractorTest.java
new file mode 100644
index 0000000..d75213c
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationChannelExtractorTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class NotificationChannelExtractorTest extends NotificationTestCase {
+
+    @Mock RankingConfig mConfig;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testExtractsUpdatedChannel() {
+        NotificationChannelExtractor extractor = new NotificationChannelExtractor();
+        extractor.setConfig(mConfig);
+
+        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+        final Notification.Builder builder = new Notification.Builder(getContext())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+        Notification n = builder.build();
+        StatusBarNotification sbn = new StatusBarNotification("", "", 0, "", 0,
+                0, n, UserHandle.ALL, null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+
+        NotificationChannel updatedChannel =
+                new NotificationChannel("a", "", IMPORTANCE_HIGH);
+        when(mConfig.getNotificationChannel(any(), anyInt(), eq("a"), eq(false)))
+                .thenReturn(updatedChannel);
+
+        assertNull(extractor.process(r));
+        assertEquals(updatedChannel, r.getChannel());
+    }
+
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
new file mode 100644
index 0000000..d2f608e
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+
+import org.junit.Test;
+
+public class NotificationIntrusivenessExtractorTest extends NotificationTestCase {
+
+    @Test
+    public void testNonIntrusive() {
+        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+        final Notification.Builder builder = new Notification.Builder(getContext())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+        Notification n = builder.build();
+        StatusBarNotification sbn = new StatusBarNotification("", "", 0, "", 0,
+                0, n, UserHandle.ALL, null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+
+        assertNull(new NotificationIntrusivenessExtractor().process(r));
+    }
+
+    @Test
+    public void testIntrusive_fillScreen() {
+        NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
+        final Notification.Builder builder = new Notification.Builder(getContext())
+                .setContentTitle("foo")
+                .setFullScreenIntent(PendingIntent.getActivity(
+                        getContext(), 0, new Intent(""), 0), true)
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+        Notification n = builder.build();
+        StatusBarNotification sbn = new StatusBarNotification("", "", 0, "", 0,
+                0, n, UserHandle.ALL, null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+
+        assertNotNull(new NotificationIntrusivenessExtractor().process(r));
+    }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 1a5814b..ae2253e 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -20,6 +20,9 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 
+import static com.android.server.notification.NotificationManagerService
+        .MESSAGE_SEND_RANKING_UPDATE;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -31,9 +34,12 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -54,6 +60,9 @@
 import android.graphics.Color;
 import android.media.AudioManager;
 import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.Process;
 import android.os.UserHandle;
 import android.provider.Settings.Secure;
@@ -63,7 +72,22 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+import android.util.ArrayMap;
 import android.util.AtomicFile;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -71,16 +95,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import com.android.server.lights.Light;
-import com.android.server.lights.LightsManager;
+import java.util.Map;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -109,6 +124,7 @@
     private AudioManager mAudioManager;
     @Mock
     ActivityManager mActivityManager;
+    NotificationManagerService.WorkerHandler mHandler;
 
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
             TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
@@ -152,6 +168,9 @@
 
         mNotificationManagerService = new TestableNotificationManagerService(mContext);
 
+        // Use this testable looper.
+        mTestableLooper = TestableLooper.get(this);
+        mHandler = mNotificationManagerService.new WorkerHandler(mTestableLooper.getLooper());
         // MockPackageManager - default returns ApplicationInfo with matching calling UID
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.uid = uid;
@@ -162,8 +181,6 @@
         final LightsManager mockLightsManager = mock(LightsManager.class);
         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
-        // Use this testable looper.
-        mTestableLooper = TestableLooper.get(this);
 
         mFile = new File(mContext.getCacheDir(), "test.xml");
         mFile.createNewFile();
@@ -174,10 +191,11 @@
                 null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
         try {
-            mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
-                    mPackageManagerClient, mockLightsManager, mNotificationListeners,
-                    mNotificationAssistants, mConditionProviders, mCompanionMgr,
-                    mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper);
+            mNotificationManagerService.init(mTestableLooper.getLooper(),
+                    mPackageManager, mPackageManagerClient, mockLightsManager,
+                    mNotificationListeners, mNotificationAssistants, mConditionProviders,
+                    mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
+                    mGroupHelper);
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                 throw e;
@@ -234,6 +252,43 @@
         return new NotificationRecord(mContext, sbn, channel);
     }
 
+    private Map<String, Answer> getSignalExtractorSideEffects() {
+        Map<String, Answer> answers = new ArrayMap<>();
+
+        answers.put("override group key", invocationOnMock -> {
+            ((NotificationRecord) invocationOnMock.getArguments()[0])
+                    .setOverrideGroupKey("bananas");
+            return null;
+        });
+        answers.put("override people", invocationOnMock -> {
+            ((NotificationRecord) invocationOnMock.getArguments()[0])
+                    .setPeopleOverride(new ArrayList<>());
+            return null;
+        });
+        answers.put("snooze criteria", invocationOnMock -> {
+            ((NotificationRecord) invocationOnMock.getArguments()[0])
+                    .setSnoozeCriteria(new ArrayList<>());
+            return null;
+        });
+        answers.put("notification channel", invocationOnMock -> {
+            ((NotificationRecord) invocationOnMock.getArguments()[0])
+                    .updateNotificationChannel(new NotificationChannel("a", "", IMPORTANCE_LOW));
+            return null;
+        });
+        answers.put("badging", invocationOnMock -> {
+            NotificationRecord r = (NotificationRecord) invocationOnMock.getArguments()[0];
+            r.setShowBadge(!r.canShowBadge());
+            return null;
+        });
+        answers.put("package visibility", invocationOnMock -> {
+            ((NotificationRecord) invocationOnMock.getArguments()[0]).setPackageVisibilityOverride(
+                    Notification.VISIBILITY_SECRET);
+            return null;
+        });
+
+        return answers;
+    }
+
     @Test
     public void testCreateNotificationChannels_SingleChannel() throws Exception {
         final NotificationChannel channel =
@@ -1317,11 +1372,59 @@
         mNotificationManagerService.addNotification(otherPackage);
 
         // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
-        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, new UserHandle(uid).getIdentifier(), 0, null));
-        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, new UserHandle(uid).getIdentifier(), 0, "tag2"));
-        assertEquals(2, mNotificationManagerService.getNotificationCountLocked("a", new UserHandle(uid).getIdentifier(), 0, "banana"));
+        int userId = new UserHandle(uid).getIdentifier();
+        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, null));
+        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, "tag2"));
+        assertEquals(2, mNotificationManagerService.getNotificationCountLocked("a", userId, 0, "banana"));
 
         // exclude a known notification - it's excluded from only the posted list, not enqueued
-        assertEquals(39, mNotificationManagerService.getNotificationCountLocked(PKG, new UserHandle(uid).getIdentifier(), 0, "tag"));
+        assertEquals(39, mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, "tag"));
+    }
+
+    @Test
+    public void testModifyAutogroup_requestsSort() throws Exception {
+        RankingHandler rh = mock(RankingHandler.class);
+        mNotificationManagerService.setRankingHandler(rh);
+
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mNotificationManagerService.addNotification(r);
+        mNotificationManagerService.addAutogroupKeyLocked(r.getKey());
+        mNotificationManagerService.removeAutogroupKeyLocked(r.getKey());
+
+        verify(rh, times(2)).requestSort();
+    }
+
+    @Test
+    public void testHandleRankingSort_sendsUpdateOnSignalExtractorChange() throws Exception {
+        mNotificationManagerService.setRankingHelper(mRankingHelper);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mNotificationManagerService.setHandler(handler);
+
+        Map<String, Answer> answers = getSignalExtractorSideEffects();
+        for (String message : answers.keySet()) {
+            mNotificationManagerService.clearNotifications();
+            final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+            mNotificationManagerService.addNotification(r);
+
+            doAnswer(answers.get(message)).when(mRankingHelper).extractSignals(r);
+
+            mNotificationManagerService.handleRankingSort();
+        }
+        verify(handler, times(answers.size())).scheduleSendRankingUpdate();
+    }
+
+    @Test
+    public void testHandleRankingSort_noUpdateWhenNoSignalChange() throws Exception {
+        mNotificationManagerService.setRankingHelper(mRankingHelper);
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mNotificationManagerService.setHandler(handler);
+
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mNotificationManagerService.addNotification(r);
+
+        mNotificationManagerService.handleRankingSort();
+        verify(handler, never()).scheduleSendRankingUpdate();
     }
 }
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 5a72e6b..801479b 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -78,6 +78,9 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 @SmallTest
@@ -630,6 +633,8 @@
 
         // all fields should be changed
         assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false));
+
+        verify(mHandler, times(1)).requestSort();
     }
 
     @Test
@@ -712,6 +717,8 @@
         assertFalse(savedChannel.canBypassDnd());
         assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
         assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
+
+        verify(mHandler, never()).requestSort();
     }
 
     @Test
@@ -1058,6 +1065,8 @@
 
         // notDeleted
         assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size());
+
+        verify(mHandler, never()).requestSort();
     }
 
     @Test
@@ -1159,6 +1168,7 @@
         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
         assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next());
+        verify(mHandler, never()).requestSort();
     }
 
     @Test
@@ -1275,6 +1285,8 @@
         actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
         assertEquals("goodbye", actual.getName());
         assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
+
+        verify(mHandler, times(1)).requestSort();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 4c77f62..b0325cb 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -347,11 +347,11 @@
     }
 
     public void testPersistentData_serializeUnserialize() {
-        byte[] serialized = PersistentData.toBytes(PersistentData.TYPE_GATEKEEPER, SOME_USER_ID,
+        byte[] serialized = PersistentData.toBytes(PersistentData.TYPE_SP, SOME_USER_ID,
                 DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, PAYLOAD);
         PersistentData deserialized = PersistentData.fromBytes(serialized);
 
-        assertEquals(PersistentData.TYPE_GATEKEEPER, deserialized.type);
+        assertEquals(PersistentData.TYPE_SP, deserialized.type);
         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, deserialized.qualityForUi);
         assertArrayEquals(PAYLOAD, deserialized.payload);
     }
@@ -371,7 +371,7 @@
         // the wire format in the future.
         byte[] serializedVersion1 = new byte[] {
                 1, /* PersistentData.VERSION_1 */
-                2, /* PersistentData.TYPE_SP */
+                1, /* PersistentData.TYPE_SP */
                 0x00, 0x00, 0x04, 0x0A,  /* SOME_USER_ID */
                 0x00, 0x03, 0x00, 0x00,  /* PASSWORD_NUMERIC_COMPLEX */
                 1, 2, -1, -2, 33, /* PAYLOAD */
@@ -385,9 +385,8 @@
 
         // Make sure the constants we use on the wire do not change.
         assertEquals(0, PersistentData.TYPE_NONE);
-        assertEquals(1, PersistentData.TYPE_GATEKEEPER);
-        assertEquals(2, PersistentData.TYPE_SP);
-        assertEquals(3, PersistentData.TYPE_SP_WEAVER);
+        assertEquals(1, PersistentData.TYPE_SP);
+        assertEquals(2, PersistentData.TYPE_SP_WEAVER);
     }
 
     public void testCredentialHash_serializeUnserialize() {
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index d11565a..eff04ab 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -201,9 +201,14 @@
                 "  time_ms: 1",
                 "  transports: 0",
                 "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
                 "    network_id <",
                 "      network_id: 102",
                 "    >",
+                "    no_default_network_duration_ms: 0",
                 "    previous_network_id <",
                 "      network_id: 101",
                 "    >",
@@ -442,6 +447,8 @@
                 "    program_updates_all: 7",
                 "    program_updates_allowing_multicast: 3",
                 "    received_ras: 10",
+                "    total_packet_dropped: 0",
+                "    total_packet_processed: 0",
                 "    zero_lifetime_ras: 1",
                 "  >",
                 ">",
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index e01469b..cc18b7f 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -256,9 +256,14 @@
                 "  time_ms: 300",
                 "  transports: 0",
                 "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
                 "    network_id <",
                 "      network_id: 102",
                 "    >",
+                "    no_default_network_duration_ms: 0",
                 "    previous_network_id <",
                 "      network_id: 101",
                 "    >",
@@ -308,6 +313,8 @@
                 "    program_updates_all: 7",
                 "    program_updates_allowing_multicast: 3",
                 "    received_ras: 10",
+                "    total_packet_dropped: 0",
+                "    total_packet_processed: 0",
                 "    zero_lifetime_ras: 1",
                 "  >",
                 ">",
@@ -367,6 +374,10 @@
                 "    event_types: 1",
                 "    event_types: 1",
                 "    event_types: 2",
+                "    getaddrinfo_error_count: 0",
+                "    getaddrinfo_query_count: 0",
+                "    gethostbyname_error_count: 0",
+                "    gethostbyname_query_count: 0",
                 "    latencies_ms: 3456",
                 "    latencies_ms: 45",
                 "    latencies_ms: 638",
@@ -384,6 +395,10 @@
                 "  dns_lookup_batch <",
                 "    event_types: 1",
                 "    event_types: 2",
+                "    getaddrinfo_error_count: 0",
+                "    getaddrinfo_query_count: 0",
+                "    gethostbyname_error_count: 0",
+                "    gethostbyname_query_count: 0",
                 "    latencies_ms: 56",
                 "    latencies_ms: 34",
                 "    return_codes: 0",
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index f98ab3d..46f395e 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -111,6 +111,10 @@
                 "    event_types: 1",
                 "    event_types: 2",
                 "    event_types: 2",
+                "    getaddrinfo_error_count: 0",
+                "    getaddrinfo_query_count: 0",
+                "    gethostbyname_error_count: 0",
+                "    gethostbyname_query_count: 0",
                 "    latencies_ms: 3456",
                 "    latencies_ms: 267",
                 "    latencies_ms: 1230",
@@ -142,6 +146,10 @@
                 "    event_types: 2",
                 "    event_types: 1",
                 "    event_types: 1",
+                "    getaddrinfo_error_count: 0",
+                "    getaddrinfo_query_count: 0",
+                "    gethostbyname_error_count: 0",
+                "    gethostbyname_query_count: 0",
                 "    latencies_ms: 56",
                 "    latencies_ms: 78",
                 "    latencies_ms: 14",
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7173775..598360c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1837,7 +1837,7 @@
     }
 
     /**
-     * This call will be deprecated and removed in an upcoming release.  It is no longer used to
+     * This call is deprecated and removed.  It is no longer used to
      * start WiFi Tethering.  Please use {@link ConnectivityManager#startTethering(int, boolean,
      * ConnectivityManager#OnStartTetheringCallback)} if
      * the caller has proper permissions.  Callers can also use the LocalOnlyHotspot feature for a
@@ -1849,8 +1849,11 @@
      * @return {@code false}
      *
      * @hide
+     * @deprecated This API is nolonger supported.
+     * @removed
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
         String packageName = mContext.getOpPackageName();