Merge "Update work notifivation settings on upgrade." into pi-dev
diff --git a/api/current.txt b/api/current.txt
index e0c45e0..f5990eb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7281,6 +7281,13 @@
     field public static final java.lang.String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
   }
 
+  public class SliceMetrics {
+    ctor public SliceMetrics(android.content.Context, android.net.Uri);
+    method public void logHidden();
+    method public void logTouch(android.net.Uri);
+    method public void logVisible();
+  }
+
   public abstract class SliceProvider extends android.content.ContentProvider {
     ctor public SliceProvider();
     method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
@@ -13612,6 +13619,7 @@
     method public void close();
     method public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, int);
     method public static android.graphics.ImageDecoder.Source createSource(android.content.ContentResolver, android.net.Uri);
+    method public static android.graphics.ImageDecoder.Source createSource(android.content.res.AssetManager, java.lang.String);
     method public static android.graphics.ImageDecoder.Source createSource(java.nio.ByteBuffer);
     method public static android.graphics.ImageDecoder.Source createSource(java.io.File);
     method public static android.graphics.Bitmap decodeBitmap(android.graphics.ImageDecoder.Source, android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
@@ -29474,7 +29482,7 @@
     field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID";
     field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
     field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
-    field public static final java.lang.String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+    field public static final java.lang.String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
     field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
     field public static final int FLAG_READER_NFC_A = 1; // 0x1
     field public static final int FLAG_READER_NFC_B = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index a6b70fd..0e33c17 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -276,8 +276,8 @@
     field public static final java.lang.String OPSTR_AUDIO_NOTIFICATION_VOLUME = "android:audio_notification_volume";
     field public static final java.lang.String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
     field public static final java.lang.String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
-    field public static final java.lang.String OPSTR_BIND_ACCESSIBILITY_SERVICE = "bind_accessibility_service";
-    field public static final java.lang.String OPSTR_CHANGE_WIFI_STATE = "change_wifi_state";
+    field public static final java.lang.String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
+    field public static final java.lang.String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
     field public static final java.lang.String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final java.lang.String OPSTR_GPS = "android:gps";
     field public static final java.lang.String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
@@ -289,7 +289,7 @@
     field public static final java.lang.String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
     field public static final java.lang.String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
     field public static final java.lang.String OPSTR_RECEIVE_EMERGENCY_BROADCAST = "android:receive_emergency_broadcast";
-    field public static final java.lang.String OPSTR_REQUEST_DELETE_PACKAGES = "request_delete_packages";
+    field public static final java.lang.String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
     field public static final java.lang.String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages";
     field public static final java.lang.String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
     field public static final java.lang.String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
diff --git a/api/test-current.txt b/api/test-current.txt
index e4caf9e..e8d27a1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -74,8 +74,8 @@
     field public static final java.lang.String OPSTR_AUDIO_NOTIFICATION_VOLUME = "android:audio_notification_volume";
     field public static final java.lang.String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
     field public static final java.lang.String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
-    field public static final java.lang.String OPSTR_BIND_ACCESSIBILITY_SERVICE = "bind_accessibility_service";
-    field public static final java.lang.String OPSTR_CHANGE_WIFI_STATE = "change_wifi_state";
+    field public static final java.lang.String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
+    field public static final java.lang.String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
     field public static final java.lang.String OPSTR_GET_ACCOUNTS = "android:get_accounts";
     field public static final java.lang.String OPSTR_GPS = "android:gps";
     field public static final java.lang.String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
@@ -87,7 +87,7 @@
     field public static final java.lang.String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
     field public static final java.lang.String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
     field public static final java.lang.String OPSTR_RECEIVE_EMERGENCY_BROADCAST = "android:receive_emergency_broadcast";
-    field public static final java.lang.String OPSTR_REQUEST_DELETE_PACKAGES = "request_delete_packages";
+    field public static final java.lang.String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
     field public static final java.lang.String OPSTR_REQUEST_INSTALL_PACKAGES = "android:request_install_packages";
     field public static final java.lang.String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
     field public static final java.lang.String OPSTR_RUN_IN_BACKGROUND = "android:run_in_background";
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 652ec9d..8b681edd 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -112,8 +112,8 @@
 }
 
 void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
-    if (android::util::kAtomsWithAttributionChain.find(event->GetTagId()) !=
-        android::util::kAtomsWithAttributionChain.end()) {
+    if (android::util::AtomsInfo::kAtomsWithAttributionChain.find(event->GetTagId()) !=
+        android::util::AtomsInfo::kAtomsWithAttributionChain.end()) {
         for (auto& value : *(event->getMutableValues())) {
             if (value.mField.getPosAtDepth(0) > kAttributionField) {
                 break;
@@ -123,12 +123,20 @@
                 updateUid(&value.mValue, hostUid);
             }
         }
-    } else if (android::util::kAtomsWithUidField.find(event->GetTagId()) !=
-                       android::util::kAtomsWithUidField.end() &&
-               event->getValues().size() > 0 && (event->getValues())[0].mValue.getType() == INT) {
-        Value& value = (*event->getMutableValues())[0].mValue;
-        const int hostUid = mUidMap->getHostUidOrSelf(value.int_value);
-        updateUid(&value, hostUid);
+    } else {
+        auto it = android::util::AtomsInfo::kAtomsWithUidField.find(event->GetTagId());
+        if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
+            int uidField = it->second;  // uidField is the field number in proto,
+                                        // starting from 1
+            if (uidField > 0 && (int)event->getValues().size() >= uidField &&
+                (event->getValues())[uidField - 1].mValue.getType() == INT) {
+                Value& value = (*event->getMutableValues())[uidField - 1].mValue;
+                const int hostUid = mUidMap->getHostUidOrSelf(value.int_value);
+                updateUid(&value, hostUid);
+            } else {
+                ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
+            }
+        }
     }
 }
 
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 19d00b7..a2a03b1 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -67,4 +67,7 @@
 extend google.protobuf.FieldOptions {
     // Flags to decorate an atom that presents a state change.
     optional StateAtomFieldOption stateFieldOption = 50000;
+
+    // Flags to decorate the uid fields in an atom.
+    optional bool is_uid = 50001 [default = false];
 }
\ No newline at end of file
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f74188f..bcbee47 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -209,7 +209,7 @@
  *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
  */
 message UidProcessStateChanged {
-    optional int32 uid = 1 [(stateFieldOption).option = PRIMARY];
+    optional int32 uid = 1 [(stateFieldOption).option = PRIMARY, (is_uid) = true];
 
     // The state, from frameworks/base/core/proto/android/app/enums.proto.
     optional android.app.ProcessStateEnum state = 2 [(stateFieldOption).option = EXCLUSIVE];
@@ -223,7 +223,7 @@
  */
 message ProcessLifeCycleStateChanged {
     // TODO: should be a string tagged w/ uid annotation
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The process name (usually same as the app name).
     optional string name = 2;
@@ -593,7 +593,7 @@
  */
 message MobileRadioPowerStateChanged {
     // TODO: Add attribution instead of uid?
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // Power state, from frameworks/base/core/proto/android/telephony/enums.proto.
     optional android.telephony.DataConnectionPowerStateEnum state = 2;
@@ -608,7 +608,7 @@
  */
 message WifiRadioPowerStateChanged {
     // TODO: Add attribution instead of uid?
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // Power state, from frameworks/base/core/proto/android/telephony/enums.proto.
     optional android.telephony.DataConnectionPowerStateEnum state = 2;
@@ -1130,7 +1130,8 @@
  */
 message DaveyOccurred {
     // The UID that logged this atom.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
+    ;
 
     // Amount of time it took to render the frame. Should be >=700ms.
     optional int64 jank_duration_millis = 2;
@@ -1187,7 +1188,7 @@
   *   frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java
  */
 message ActivityForegroundStateChanged {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     optional string pkg_name = 2;
     optional string class_name = 3;
 
@@ -1205,7 +1206,7 @@
  */
 message DropboxErrorChanged {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // Tag used when recording this error to dropbox. Contains data_ or system_ prefix.
     optional string tag = 2;
@@ -1236,7 +1237,7 @@
  */
 message AppBreadcrumbReported {
     // The uid of the application that sent this custom atom.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // An arbitrary label chosen by the developer. For Android P, the label should be in [0, 16).
     optional int32 label = 2;
@@ -1260,7 +1261,7 @@
  */
 message AnomalyDetected {
     // Uid that owns the config whose anomaly detection alert fired.
-    optional int32 config_uid = 1;
+    optional int32 config_uid = 1 [(is_uid) = true];
 
     // Id of the config whose anomaly detection alert fired.
     optional int64 config_id = 2;
@@ -1271,7 +1272,7 @@
 
 message AppStartChanged {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The app package name.
     optional string pkg_name = 2;
@@ -1318,7 +1319,7 @@
 
 message AppStartCancelChanged {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The app package name.
     optional string pkg_name = 2;
@@ -1338,7 +1339,7 @@
 
 message AppStartFullyDrawnChanged {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The app package name.
     optional string pkg_name = 2;
@@ -1369,7 +1370,7 @@
  */
 message PictureInPictureStateChanged {
     // -1 if it is not available
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     optional string short_name = 2;
 
@@ -1388,7 +1389,7 @@
  *     services/core/java/com/android/server/wm/Session.java
  */
 message OverlayStateChanged {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     optional string package_name = 2;
 
@@ -1409,7 +1410,7 @@
  *     //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
  */
 message ForegroundServiceStateChanged {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     // package_name + "/" + class_name
     optional string short_name = 2;
 
@@ -1429,6 +1430,7 @@
  *   frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
  */
 message IsolatedUidChanged {
+    // NOTE: DO NOT annotate uid field in this atom. This atom is specially handled in statsd.
     // The host UID. Generally, we should attribute metrics from the isolated uid to the host uid.
     optional int32 parent_uid = 1;
 
@@ -1450,7 +1452,7 @@
 message PacketWakeupOccurred {
     // The uid owning the socket into which the packet was delivered, or -1 if the packet was
     // delivered nowhere.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     // The interface name on which the packet was received.
     optional string iface = 2;
     // The ethertype value of the packet.
@@ -1478,7 +1480,7 @@
  */
 message AppStartMemoryStateCaptured {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The process name.
     optional string process_name = 2;
@@ -1524,7 +1526,7 @@
  */
 message LmkKillOccurred {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The process name.
     optional string process_name = 2;
@@ -1556,7 +1558,7 @@
  */
 message AppDied {
     // timestamp(elapsedRealtime) of record creation
-    optional uint64 timestamp_millis = 1;
+    optional uint64 timestamp_millis = 1 [(stateFieldOption).option = EXCLUSIVE];
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -1570,7 +1572,7 @@
  *   StatsCompanionService (using BatteryStats to get which interfaces are wifi)
  */
 message WifiBytesTransfer {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     optional int64 rx_bytes = 2;
 
@@ -1588,9 +1590,10 @@
  *   StatsCompanionService (using BatteryStats to get which interfaces are wifi)
  */
 message WifiBytesTransferByFgBg {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
-    // 1 denotes foreground and 0 denotes background. This is called Set in NetworkStats.
+    // 1 denotes foreground and 0 denotes background. This is called Set in
+    // NetworkStats.
     optional int32 is_foreground = 2;
 
     optional int64 rx_bytes = 3;
@@ -1609,7 +1612,7 @@
  *   StatsCompanionService (using BatteryStats to get which interfaces are mobile data)
  */
 message MobileBytesTransfer {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     optional int64 rx_bytes = 2;
 
@@ -1627,9 +1630,10 @@
  *   StatsCompanionService (using BatteryStats to get which interfaces are mobile data)
  */
 message MobileBytesTransferByFgBg {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
-    // 1 denotes foreground and 0 denotes background. This is called Set in NetworkStats.
+    // 1 denotes foreground and 0 denotes background. This is called Set in
+    // NetworkStats.
     optional int32 is_foreground = 2;
 
     optional int64 rx_bytes = 3;
@@ -1648,7 +1652,7 @@
  *   StatsCompanionService
  */
 message BluetoothBytesTransfer {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     optional int64 rx_bytes = 2;
 
@@ -1708,7 +1712,7 @@
  * Note that isolated process uid time should be attributed to host uids.
  */
 message CpuTimePerUid {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     optional uint64 user_time_millis = 2;
     optional uint64 sys_time_millis = 3;
 }
@@ -1719,7 +1723,7 @@
  * For each uid, we order the time by descending frequencies.
  */
 message CpuTimePerUidFreq {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     optional uint32 freq_index = 2;
     optional uint64 time_millis = 3;
 }
@@ -1801,7 +1805,7 @@
  */
 message ProcessMemoryState {
     // The uid if available. -1 means not available.
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
 
     // The process name.
     optional string process_name = 2;
@@ -1853,7 +1857,7 @@
  * The file contains a monotonically increasing count of time for a single boot.
  */
 message CpuActiveTime {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     optional uint64 time_millis = 2;
 }
 
@@ -1867,7 +1871,7 @@
  * The file contains a monotonically increasing count of time for a single boot.
  */
 message CpuClusterTime {
-    optional int32 uid = 1;
+    optional int32 uid = 1 [(is_uid) = true];
     optional int32 cluster_index = 2;
     optional uint64 time_millis = 3;
 }
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index 0b0c5c4..ea23623 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -112,7 +112,8 @@
         VLOG("Unknown pull atom id %d", tagId);
         return;
     }
-    if (android::util::kAtomsWithUidField.find(tagId) == android::util::kAtomsWithUidField.end()) {
+    if (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) ==
+        android::util::AtomsInfo::kAtomsWithUidField.end()) {
         VLOG("No uid to merge for atom %d", tagId);
         return;
     }
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 778eb8e..bd8b293 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -134,8 +134,8 @@
     uint64_t wrapperToken =
             mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
     const bool truncateTimestamp =
-        android::util::kNotTruncatingTimestampAtomWhiteList.find(event.GetTagId()) ==
-        android::util::kNotTruncatingTimestampAtomWhiteList.end();
+            android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(event.GetTagId()) ==
+            android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
     if (truncateTimestamp) {
         mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
             (long long)truncateTimestampNsToFiveMinutes(event.GetElapsedTimestampNs()));
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 55a281e..49034ac 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -195,8 +195,9 @@
                     protoOutput->end(atomsToken);
                 }
                 const bool truncateTimestamp =
-                    android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) ==
-                    android::util::kNotTruncatingTimestampAtomWhiteList.end();
+                        android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(
+                                mTagId) ==
+                        android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
                 const int64_t wall_clock_ns = truncateTimestamp ?
                     truncateTimestampNsToFiveMinutes(getWallClockNs()) : getWallClockNs();
                 for (const auto& atom : bucket.mGaugeAtoms) {
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 901f500..c6112fd 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -170,9 +170,10 @@
     // 1. must not have "stop". must have "dimension"
     if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) {
         // TODO: need to check the start atom matcher too.
-        auto it = android::util::kStateAtomsFieldOptions.find(simplePredicate.dimensions().field());
+        auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find(
+                simplePredicate.dimensions().field());
         // 2. must be based on a state atom.
-        if (it != android::util::kStateAtomsFieldOptions.end()) {
+        if (it != android::util::AtomsInfo::kStateAtomsFieldOptions.end()) {
             // 3. dimension must be primary fields + state field IN ORDER
             size_t expectedDimensionCount = it->second.primaryFields.size() + 1;
             vector<Matcher> dimensions;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 99bcdb9f..459a587 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -64,6 +64,7 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.ImageDecoder;
 import android.hardware.display.DisplayManagerGlobal;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
@@ -5551,6 +5552,13 @@
 
         Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
 
+        // Prior to P, internal calls to decode Bitmaps used BitmapFactory,
+        // which may scale up to account for density. In P, we switched to
+        // ImageDecoder, which skips the upscale to save memory. ImageDecoder
+        // needs to still scale up in older apps, in case they rely on the
+        // size of the Bitmap without considering its density.
+        ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;
+
         /*
          * Before spawning a new process, reset the time zone to be the system time zone.
          * This needs to be done because the system time zone could have changed after the
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 14edd31..4690211 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -499,13 +499,14 @@
     public static final String OPSTR_RUN_ANY_IN_BACKGROUND = "android:run_any_in_background";
     /** @hide */
     @SystemApi @TestApi
-    public static final String OPSTR_CHANGE_WIFI_STATE = "change_wifi_state";
+    public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
     /** @hide */
     @SystemApi @TestApi
-    public static final String OPSTR_REQUEST_DELETE_PACKAGES = "request_delete_packages";
+    public static final String OPSTR_REQUEST_DELETE_PACKAGES = "android:request_delete_packages";
     /** @hide */
     @SystemApi @TestApi
-    public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "bind_accessibility_service";
+    public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE =
+            "android:bind_accessibility_service";
 
     // Warning: If an permission is added here it also has to be added to
     // com.android.packageinstaller.permission.utils.EventLogger
diff --git a/core/java/android/app/slice/SliceMetrics.java b/core/java/android/app/slice/SliceMetrics.java
new file mode 100644
index 0000000..a7069bc
--- /dev/null
+++ b/core/java/android/app/slice/SliceMetrics.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 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 android.app.slice;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.internal.logging.MetricsLogger;
+
+/**
+ * Metrics interface for slices.
+ *
+ * This is called by SliceView, so Slice develoers should
+ * not need to reference this class.
+ *
+ * @see androidx.slice.widget.SliceView
+ */
+public class SliceMetrics {
+
+    private static final String TAG = "SliceMetrics";
+    private MetricsLogger mMetricsLogger;
+
+    /**
+     * An object to be used throughout the life of a slice to register events.
+     */
+    public SliceMetrics(@NonNull Context context, @NonNull Uri uri) {
+        mMetricsLogger = new MetricsLogger();
+    }
+
+    /**
+     * To be called whenever the slice becomes visible to the user.
+     */
+    public void logVisible() {
+    }
+
+    /**
+     * To be called whenever the slice becomes invisible to the user.
+     */
+    public void logHidden() {
+    }
+
+    /**
+     * To be called whenever the use interacts with a slice.
+     *@param subSlice The URI of the sub-slice that is the subject of the interaction.
+     */
+    public void logTouch(@NonNull Uri subSlice) {
+    }
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index b02d48d..c3f23a1 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -225,7 +225,7 @@
      * Indicates the Secure Element on which the transaction occurred.
      * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc.
      */
-    public static final String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+    public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
 
     public static final int STATE_OFF = 1;
     public static final int STATE_TURNING_ON = 2;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 79b6ea6..50d9767 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9541,6 +9541,12 @@
         public static final String BLE_SCAN_LOW_LATENCY_INTERVAL_MS =
                 "ble_scan_low_latency_interval_ms";
 
+        /**
+         * The mode that BLE scanning clients will be moved to when in the background.
+         * @hide
+         */
+        public static final String BLE_SCAN_BACKGROUND_MODE = "ble_scan_background_mode";
+
        /**
         * Used to save the Wifi_ON state prior to tethering.
         * This state will be checked to restore Wifi after
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 740a387..3830b7a 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -97,7 +97,7 @@
     private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS =
             Policy.getAllSuppressedVisualEffects();
 
-    public static final int XML_VERSION = 5;
+    public static final int XML_VERSION = 6;
     public static final String ZEN_TAG = "zen";
     private static final String ZEN_ATT_VERSION = "version";
     private static final String ZEN_ATT_USER = "user";
@@ -516,11 +516,17 @@
         throw new IllegalStateException("Failed to reach END_DOCUMENT");
     }
 
-    public void writeXml(XmlSerializer out) throws IOException {
+    /**
+     * Writes XML of current ZenModeConfig
+     * @param out serializer
+     * @param version uses XML_VERSION if version is null
+     * @throws IOException
+     */
+    public void writeXml(XmlSerializer out, Integer version) throws IOException {
         out.startTag(null, ZEN_TAG);
-        out.attribute(null, ZEN_ATT_VERSION, Integer.toString(XML_VERSION));
+        out.attribute(null, ZEN_ATT_VERSION, version == null
+                ? Integer.toString(XML_VERSION) : Integer.toString(version));
         out.attribute(null, ZEN_ATT_USER, Integer.toString(user));
-
         out.startTag(null, ALLOW_TAG);
         out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls));
         out.attribute(null, ALLOW_ATT_REPEAT_CALLERS, Boolean.toString(allowRepeatCallers));
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 5950436..21b7d25 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -55,10 +55,13 @@
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
         List<NotificationChannel> channelsList = new ArrayList<NotificationChannel>();
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel keyboard = new NotificationChannel(
                 VIRTUAL_KEYBOARD,
                 context.getString(R.string.notification_channel_virtual_keyboard),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        keyboard.setBypassDnd(true);
+        keyboard.setBlockableSystem(true);
+        channelsList.add(keyboard);
 
         final NotificationChannel physicalKeyboardChannel = new NotificationChannel(
                 PHYSICAL_KEYBOARD,
@@ -66,81 +69,105 @@
                 NotificationManager.IMPORTANCE_DEFAULT);
         physicalKeyboardChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
                 Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        physicalKeyboardChannel.setBlockableSystem(true);
         channelsList.add(physicalKeyboardChannel);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel security = new NotificationChannel(
                 SECURITY,
                 context.getString(R.string.notification_channel_security),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        security.setBypassDnd(true);
+        channelsList.add(security);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel car = new NotificationChannel(
                 CAR_MODE,
                 context.getString(R.string.notification_channel_car_mode),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        car.setBlockableSystem(true);
+        car.setBypassDnd(true);
+        channelsList.add(car);
 
         channelsList.add(newAccountChannel(context));
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel developer = new NotificationChannel(
                 DEVELOPER,
                 context.getString(R.string.notification_channel_developer),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        developer.setBypassDnd(true);
+        developer.setBlockableSystem(true);
+        channelsList.add(developer);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel updates = new NotificationChannel(
                 UPDATES,
                 context.getString(R.string.notification_channel_updates),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        updates.setBypassDnd(true);
+        channelsList.add(updates);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel network = new NotificationChannel(
                 NETWORK_STATUS,
                 context.getString(R.string.notification_channel_network_status),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        network.setBypassDnd(true);
+        channelsList.add(network);
 
         final NotificationChannel networkAlertsChannel = new NotificationChannel(
                 NETWORK_ALERTS,
                 context.getString(R.string.notification_channel_network_alerts),
                 NotificationManager.IMPORTANCE_HIGH);
-        networkAlertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
-                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        networkAlertsChannel.setBypassDnd(true);
+        networkAlertsChannel.setBlockableSystem(true);
         channelsList.add(networkAlertsChannel);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel networkAvailable = new NotificationChannel(
                 NETWORK_AVAILABLE,
                 context.getString(R.string.notification_channel_network_available),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        networkAvailable.setBlockableSystem(true);
+        networkAvailable.setBypassDnd(true);
+        channelsList.add(networkAvailable);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel vpn = new NotificationChannel(
                 VPN,
                 context.getString(R.string.notification_channel_vpn),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        vpn.setBypassDnd(true);
+        channelsList.add(vpn);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel deviceAdmin = new NotificationChannel(
                 DEVICE_ADMIN,
                 context.getString(R.string.notification_channel_device_admin),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        deviceAdmin.setBypassDnd(true);
+        channelsList.add(deviceAdmin);
 
         final NotificationChannel alertsChannel = new NotificationChannel(
                 ALERTS,
                 context.getString(R.string.notification_channel_alerts),
                 NotificationManager.IMPORTANCE_DEFAULT);
-        alertsChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
-                Notification.AUDIO_ATTRIBUTES_DEFAULT);
+        alertsChannel.setBypassDnd(true);
         channelsList.add(alertsChannel);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel retail = new NotificationChannel(
                 RETAIL_MODE,
                 context.getString(R.string.notification_channel_retail_mode),
-                NotificationManager.IMPORTANCE_LOW));
+                NotificationManager.IMPORTANCE_LOW);
+        retail.setBypassDnd(true);
+        channelsList.add(retail);
 
-        channelsList.add(new NotificationChannel(
+        final NotificationChannel usb = new NotificationChannel(
                 USB,
                 context.getString(R.string.notification_channel_usb),
-                NotificationManager.IMPORTANCE_MIN));
+                NotificationManager.IMPORTANCE_MIN);
+        usb.setBypassDnd(true);
+        channelsList.add(usb);
 
         NotificationChannel foregroundChannel = new NotificationChannel(
                 FOREGROUND_SERVICE,
                 context.getString(R.string.notification_channel_foreground_service),
                 NotificationManager.IMPORTANCE_LOW);
         foregroundChannel.setBlockableSystem(true);
+        foregroundChannel.setBypassDnd(true);
         channelsList.add(foregroundChannel);
 
         NotificationChannel heavyWeightChannel = new NotificationChannel(
@@ -152,16 +179,19 @@
                 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                 .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
                 .build());
+        heavyWeightChannel.setBypassDnd(true);
         channelsList.add(heavyWeightChannel);
 
         NotificationChannel systemChanges = new NotificationChannel(SYSTEM_CHANGES,
                 context.getString(R.string.notification_channel_system_changes),
                 NotificationManager.IMPORTANCE_LOW);
+        systemChanges.setBypassDnd(true);
         channelsList.add(systemChanges);
 
         NotificationChannel dndChanges = new NotificationChannel(DO_NOT_DISTURB,
                 context.getString(R.string.notification_channel_do_not_disturb),
                 NotificationManager.IMPORTANCE_LOW);
+        dndChanges.setBypassDnd(true);
         channelsList.add(dndChanges);
 
         nm.createNotificationChannels(channelsList);
@@ -178,10 +208,12 @@
     }
 
     private static NotificationChannel newAccountChannel(Context context) {
-        return new NotificationChannel(
+        final NotificationChannel acct = new NotificationChannel(
                 ACCOUNT,
                 context.getString(R.string.notification_channel_account),
                 NotificationManager.IMPORTANCE_LOW);
+        acct.setBypassDnd(true);
+        return acct;
     }
 
     private SystemNotificationChannels() {}
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index f422065..c2fedf5 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -56,7 +56,7 @@
     // Number of "missed vsync" events.
     optional int32 missed_vsync_count = 3;
 
-    // Number of "high input latency" events.
+    // Number of frames in triple-buffering scenario (high input latency)
     optional int32 high_input_latency_count = 4;
 
     // Number of "slow UI thread" events.
@@ -67,6 +67,9 @@
 
     // Number of "slow draw" events.
     optional int32 slow_draw_count = 7;
+
+    // Number of frames that missed their deadline (aka, visibly janked)
+    optional int32 missed_deadline_count = 8;
 }
 
 message GraphicsStatsHistogramBucketProto {
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 5c40e5f..cccd2fe 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -93,7 +93,8 @@
     message ServiceProto {
         option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
-        repeated string name = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
+        // Package or component name.
+        repeated string name = 1;
         optional int32 user_id = 2;
         optional bool is_primary = 3;
     }
@@ -169,16 +170,16 @@
 message ZenRuleProto {
     option (android.msg_privacy).dest = DEST_EXPLICIT;
 
-    // Required for automatic (unique).
+    // Required for automatic ZenRules (unique).
     optional string id = 1;
-    // Required for automatic.
+    // Required for automatic ZenRules.
     optional string name = 2;
-    // Required for automatic.
+    // Required for automatic ZenRules.
     optional int64 creation_time_ms = 3 [
         (android.privacy).dest = DEST_AUTOMATIC
     ];
     optional bool enabled = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
-    // Package name, only used for manual rules.
+    // Package name, only used for manual ZenRules.
     optional string enabler = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
     // User manually disabled this instance.
     optional bool is_snoozing = 6 [
@@ -188,7 +189,7 @@
         (android.privacy).dest = DEST_AUTOMATIC
     ];
 
-    // Required for automatic.
+    // Required for automatic ZenRules.
     optional string condition_id = 8;
     optional ConditionProto condition = 9;
     optional android.content.ComponentNameProto component = 10;
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 2d3cd1c..f1b61a7 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -18,7 +18,7 @@
 -->
 
 <!-- Default configuration for zen mode.  See android.service.notification.ZenModeConfig. -->
-<zen version="5">
+<zen version="6">
     <allow alarms="true" media="true" system="false" calls="false" messages="false" reminders="false"
            events="false" />
     <!-- all visual effects that exist as of P -->
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index cc36b96..63343be 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -129,6 +129,7 @@
                     Settings.Global.BLE_SCAN_BALANCED_INTERVAL_MS,
                     Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS,
                     Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS,
+                    Settings.Global.BLE_SCAN_BACKGROUND_MODE,
                     Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
                     Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
                     Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 8196d66..2f09c65 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -26,6 +26,7 @@
 import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
 import android.content.res.AssetManager.AssetInputStream;
 import android.content.res.Resources;
 import android.graphics.drawable.AnimatedImageDrawable;
@@ -33,6 +34,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.NinePatchDrawable;
 import android.net.Uri;
+import android.os.Build;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.DisplayMetrics;
@@ -57,6 +59,9 @@
  *  Class for decoding images as {@link Bitmap}s or {@link Drawable}s.
  */
 public final class ImageDecoder implements AutoCloseable {
+    /** @hide **/
+    public static int sApiLevel;
+
     /**
      *  Source of the encoded image data.
      */
@@ -294,25 +299,13 @@
 
         @Override
         public ImageDecoder createImageDecoder() throws IOException {
-            ImageDecoder decoder = null;
             synchronized (this) {
                 if (mAssetInputStream == null) {
                     throw new IOException("Cannot reuse AssetInputStreamSource");
                 }
                 AssetInputStream ais = mAssetInputStream;
                 mAssetInputStream = null;
-                try {
-                    long asset = ais.getNativeAsset();
-                    decoder = nCreate(asset);
-                } finally {
-                    if (decoder == null) {
-                        IoUtils.closeQuietly(ais);
-                    } else {
-                        decoder.mInputStream = ais;
-                        decoder.mOwnsInputStream = true;
-                    }
-                }
-                return decoder;
+                return createFromAsset(ais);
             }
         }
     }
@@ -336,31 +329,53 @@
 
         @Override
         public ImageDecoder createImageDecoder() throws IOException {
-            // This is just used in order to access the underlying Asset and
-            // keep it alive. FIXME: Can we skip creating this object?
-            InputStream is = null;
-            ImageDecoder decoder = null;
             TypedValue value = new TypedValue();
-            try {
-                is = mResources.openRawResource(mResId, value);
+            // This is just used in order to access the underlying Asset and
+            // keep it alive.
+            InputStream is = mResources.openRawResource(mResId, value);
 
-                if (value.density == TypedValue.DENSITY_DEFAULT) {
-                    mResDensity = DisplayMetrics.DENSITY_DEFAULT;
-                } else if (value.density != TypedValue.DENSITY_NONE) {
-                    mResDensity = value.density;
-                }
-
-                long asset = ((AssetInputStream) is).getNativeAsset();
-                decoder = nCreate(asset);
-            } finally {
-                if (decoder == null) {
-                    IoUtils.closeQuietly(is);
-                } else {
-                    decoder.mInputStream = is;
-                    decoder.mOwnsInputStream = true;
-                }
+            if (value.density == TypedValue.DENSITY_DEFAULT) {
+                mResDensity = DisplayMetrics.DENSITY_DEFAULT;
+            } else if (value.density != TypedValue.DENSITY_NONE) {
+                mResDensity = value.density;
             }
-            return decoder;
+
+            return createFromAsset((AssetInputStream) is);
+        }
+    }
+
+    /**
+     *  ImageDecoder will own the AssetInputStream.
+     */
+    private static ImageDecoder createFromAsset(AssetInputStream ais) throws IOException {
+        ImageDecoder decoder = null;
+        try {
+            long asset = ais.getNativeAsset();
+            decoder = nCreate(asset);
+        } finally {
+            if (decoder == null) {
+                IoUtils.closeQuietly(ais);
+            } else {
+                decoder.mInputStream = ais;
+                decoder.mOwnsInputStream = true;
+            }
+        }
+        return decoder;
+    }
+
+    private static class AssetSource extends Source {
+        AssetSource(@NonNull AssetManager assets, @NonNull String fileName) {
+            mAssets = assets;
+            mFileName = fileName;
+        }
+
+        private final AssetManager mAssets;
+        private final String mFileName;
+
+        @Override
+        public ImageDecoder createImageDecoder() throws IOException {
+            InputStream is = mAssets.open(mFileName);
+            return createFromAsset((AssetInputStream) is);
         }
     }
 
@@ -581,6 +596,14 @@
     }
 
     /**
+     * Create a new {@link Source} from a file in the "assets" directory.
+     */
+    @NonNull
+    public static Source createSource(@NonNull AssetManager assets, @NonNull String fileName) {
+        return new AssetSource(assets, fileName);
+    }
+
+    /**
      * Create a new {@link Source} from a byte array.
      *
      * @param data byte array of compressed image data.
@@ -1243,17 +1266,19 @@
             return srcDensity;
         }
 
-        // downscale the bitmap if the asset has a higher density than the default
+        // For P and above, only resize if it would be a downscale. Scale up prior
+        // to P in case the app relies on the Bitmap's size without considering density.
         final int dstDensity = src.computeDstDensity();
-        if (srcDensity != Bitmap.DENSITY_NONE && srcDensity > dstDensity) {
-            float scale = (float) dstDensity / srcDensity;
-            int scaledWidth = (int) (decoder.mWidth * scale + 0.5f);
-            int scaledHeight = (int) (decoder.mHeight * scale + 0.5f);
-            decoder.setResize(scaledWidth, scaledHeight);
-            return dstDensity;
+        if (srcDensity == Bitmap.DENSITY_NONE || srcDensity == dstDensity
+                || (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P)) {
+            return srcDensity;
         }
 
-        return srcDensity;
+        float scale = (float) dstDensity / srcDensity;
+        int scaledWidth = (int) (decoder.mWidth * scale + 0.5f);
+        int scaledHeight = (int) (decoder.mHeight * scale + 0.5f);
+        decoder.setResize(scaledWidth, scaledHeight);
+        return dstDensity;
     }
 
     @NonNull
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index cf29e43..81a7980 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -38,16 +38,27 @@
 namespace uirenderer {
 
 struct Comparison {
+    JankType type;
+    std::function<int64_t(nsecs_t)> computeThreadshold;
     FrameInfoIndex start;
     FrameInfoIndex end;
 };
 
-static const Comparison COMPARISONS[] = {
-        {FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync},
-        {FrameInfoIndex::OldestInputEvent, FrameInfoIndex::Vsync},
-        {FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart},
-        {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart},
-        {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted},
+static const std::array<Comparison, 4> COMPARISONS{
+        Comparison{JankType::kMissedVsync, [](nsecs_t) { return 1; }, FrameInfoIndex::IntendedVsync,
+                   FrameInfoIndex::Vsync},
+
+        Comparison{JankType::kSlowUI,
+                   [](nsecs_t frameInterval) { return static_cast<int64_t>(.5 * frameInterval); },
+                   FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart},
+
+        Comparison{JankType::kSlowSync,
+                   [](nsecs_t frameInterval) { return static_cast<int64_t>(.2 * frameInterval); },
+                   FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart},
+
+        Comparison{JankType::kSlowRT,
+                   [](nsecs_t frameInterval) { return static_cast<int64_t>(.75 * frameInterval); },
+                   FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted},
 };
 
 // If the event exceeds 10 seconds throw it away, this isn't a jank event
@@ -91,24 +102,10 @@
 
 void JankTracker::setFrameInterval(nsecs_t frameInterval) {
     mFrameInterval = frameInterval;
-    mThresholds[kMissedVsync] = 1;
-    /*
-     * Due to interpolation and sample rate differences between the touch
-     * panel and the display (example, 85hz touch panel driving a 60hz display)
-     * we call high latency 1.5 * frameinterval
-     *
-     * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
-     * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
-     * Thus this must always be larger than frameInterval, or it will fail
-     */
-    mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
 
-    // Note that these do not add up to 1. This is intentional. It's to deal
-    // with variance in values, and should be sort of an upper-bound on what
-    // is reasonable to expect.
-    mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
-    mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
-    mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
+    for (auto& comparison : COMPARISONS) {
+        mThresholds[comparison.type] = comparison.computeThreadshold(frameInterval);
+    }
 }
 
 void JankTracker::finishFrame(const FrameInfo& frame) {
@@ -129,28 +126,48 @@
             totalDuration -= forgiveAmount;
         }
     }
+
     LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration);
     mData->reportFrame(totalDuration);
     (*mGlobalData)->reportFrame(totalDuration);
 
-    // Keep the fast path as fast as possible.
-    if (CC_LIKELY(totalDuration < mFrameInterval)) {
-        return;
-    }
-
     // Only things like Surface.lockHardwareCanvas() are exempt from tracking
-    if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) {
+    if (CC_UNLIKELY(frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS)) {
         return;
     }
 
-    mData->reportJank();
-    (*mGlobalData)->reportJank();
+    if (totalDuration > mFrameInterval) {
+        mData->reportJank();
+        (*mGlobalData)->reportJank();
+    }
 
-    for (int i = 0; i < NUM_BUCKETS; i++) {
-        int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end);
-        if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
-            mData->reportJankType((JankType)i);
-            (*mGlobalData)->reportJankType((JankType)i);
+    bool isTripleBuffered = mSwapDeadline > frame[FrameInfoIndex::IntendedVsync];
+
+    mSwapDeadline = std::max(mSwapDeadline + mFrameInterval,
+                             frame[FrameInfoIndex::IntendedVsync] + mFrameInterval);
+
+    // If we hit the deadline, cool!
+    if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) {
+        if (isTripleBuffered) {
+            mData->reportJankType(JankType::kHighInputLatency);
+            (*mGlobalData)->reportJankType(JankType::kHighInputLatency);
+        }
+        return;
+    }
+
+    mData->reportJankType(JankType::kMissedDeadline);
+    (*mGlobalData)->reportJankType(JankType::kMissedDeadline);
+
+    // Janked, reset the swap deadline
+    nsecs_t jitterNanos = frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::Vsync];
+    nsecs_t lastFrameOffset = jitterNanos % mFrameInterval;
+    mSwapDeadline = frame[FrameInfoIndex::FrameCompleted] - lastFrameOffset + mFrameInterval;
+
+    for (auto& comparison : COMPARISONS) {
+        int64_t delta = frame.duration(comparison.start, comparison.end);
+        if (delta >= mThresholds[comparison.type] && delta < IGNORE_EXCEEDING) {
+            mData->reportJankType(comparison.type);
+            (*mGlobalData)->reportJankType(comparison.type);
         }
     }
 
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index dc6a7ff..110211e 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -75,6 +75,7 @@
 
     std::array<int64_t, NUM_BUCKETS> mThresholds;
     int64_t mFrameInterval;
+    nsecs_t mSwapDeadline;
     // The amount of time we will erase from the total duration to account
     // for SF vsync offsets with HWC2 blocking dequeueBuffers.
     // (Vsync + mDequeueBlockTolerance) is the point at which we expect
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index b392ecd..f9cf549 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -23,8 +23,7 @@
 
 static const char* JANK_TYPE_NAMES[] = {
         "Missed Vsync",        "High input latency",       "Slow UI thread",
-        "Slow bitmap uploads", "Slow issue draw commands",
-};
+        "Slow bitmap uploads", "Slow issue draw commands", "Frame deadline missed"};
 
 // The bucketing algorithm controls so to speak
 // If a frame is <= to this it goes in bucket 0
diff --git a/libs/hwui/ProfileData.h b/libs/hwui/ProfileData.h
index 1e688ab..564920b 100644
--- a/libs/hwui/ProfileData.h
+++ b/libs/hwui/ProfileData.h
@@ -33,6 +33,7 @@
     kSlowUI,
     kSlowSync,
     kSlowRT,
+    kMissedDeadline,
 
     // must be last
     NUM_BUCKETS,
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index e0303a8..599226b 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -176,6 +176,8 @@
     summary->set_slow_bitmap_upload_count(summary->slow_bitmap_upload_count() +
                                           data->jankTypeCount(kSlowSync));
     summary->set_slow_draw_count(summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
+    summary->set_missed_deadline_count(summary->missed_deadline_count()
+            + data->jankTypeCount(kMissedDeadline));
 
     bool creatingHistogram = false;
     if (proto->histogram_size() == 0) {
@@ -246,6 +248,7 @@
     dprintf(fd, "\nNumber Slow UI thread: %d", summary.slow_ui_thread_count());
     dprintf(fd, "\nNumber Slow bitmap uploads: %d", summary.slow_bitmap_upload_count());
     dprintf(fd, "\nNumber Slow issue draw commands: %d", summary.slow_draw_count());
+    dprintf(fd, "\nNumber Frame deadline missed: %d", summary.missed_deadline_count());
     dprintf(fd, "\nHISTOGRAM:");
     for (const auto& it : proto->histogram()) {
         dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
diff --git a/libs/hwui/tests/common/scenes/JankyScene.cpp b/libs/hwui/tests/common/scenes/JankyScene.cpp
new file mode 100644
index 0000000..f5e6b31
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/JankyScene.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include "TestSceneBase.h"
+
+#include <unistd.h>
+
+class JankyScene;
+
+static TestScene::Registrar _JankyScene(TestScene::Info{
+        "janky",
+        "A scene that intentionally janks just enough to stay in "
+        "triple buffering.",
+        TestScene::simpleCreateScene<JankyScene>});
+
+class JankyScene : public TestScene {
+public:
+    sp<RenderNode> card;
+
+    void createContent(int width, int height, Canvas& canvas) override {
+        card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
+            canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
+        });
+        canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);  // background
+        canvas.drawRenderNode(card.get());
+    }
+
+    void doFrame(int frameNr) override {
+        int curFrame = frameNr % 150;
+        if (curFrame & 1) {
+            usleep(15000);
+        }
+        // we animate left and top coordinates, which in turn animates width and
+        // height (bottom/right coordinates are fixed)
+        card->mutateStagingProperties().setLeftTop(curFrame, curFrame);
+        card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+    }
+};
\ No newline at end of file
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 6dd4f69..37c5785 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -186,6 +186,13 @@
     public abstract long getTimestamp();
 
     /**
+     * Get the transformation associated with this frame.
+     * @return The window transformation that needs to be applied for this frame.
+     * @hide
+     */
+    public abstract int getTransform();
+
+    /**
      * Get the {@link android.hardware.HardwareBuffer HardwareBuffer} handle of the input image
      * intended for GPU and/or hardware access.
      * <p>
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index fb0de5c..56edace 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -876,6 +876,12 @@
         }
 
         @Override
+        public int getTransform() {
+            throwISEIfImageIsInvalid();
+            return mTransform;
+        }
+
+        @Override
         public HardwareBuffer getHardwareBuffer() {
             throwISEIfImageIsInvalid();
             return nativeGetHardwareBuffer();
@@ -1013,6 +1019,11 @@
          */
         private long mTimestamp;
 
+        /**
+         * This field is set by native code during nativeImageSetup().
+         */
+        private int mTransform;
+
         private SurfacePlane[] mPlanes;
         private int mFormat = ImageFormat.UNKNOWN;
         // If this image is detached from the ImageReader.
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 2b7309f..8ee27ae 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -371,7 +371,7 @@
 
         Rect crop = image.getCropRect();
         nativeQueueInputImage(mNativeContext, image, image.getTimestamp(), crop.left, crop.top,
-                crop.right, crop.bottom);
+                crop.right, crop.bottom, image.getTransform());
 
         /**
          * Only remove and cleanup the Images that are owned by this
@@ -557,7 +557,8 @@
         // buffer caused leak.
         Rect crop = image.getCropRect();
         nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), image.getFormat(),
-                image.getTimestamp(), crop.left, crop.top, crop.right, crop.bottom);
+                image.getTimestamp(), crop.left, crop.top, crop.right, crop.bottom,
+                image.getTransform());
     }
 
     /**
@@ -674,6 +675,8 @@
         private final long DEFAULT_TIMESTAMP = Long.MIN_VALUE;
         private long mTimestamp = DEFAULT_TIMESTAMP;
 
+        private int mTransform = 0; //Default no transform
+
         public WriterSurfaceImage(ImageWriter writer) {
             mOwner = writer;
         }
@@ -711,6 +714,13 @@
         }
 
         @Override
+        public int getTransform() {
+            throwISEIfImageIsInvalid();
+
+            return mTransform;
+        }
+
+        @Override
         public long getTimestamp() {
             throwISEIfImageIsInvalid();
 
@@ -856,11 +866,11 @@
     private synchronized native void nativeDequeueInputImage(long nativeCtx, Image wi);
 
     private synchronized native void nativeQueueInputImage(long nativeCtx, Image image,
-            long timestampNs, int left, int top, int right, int bottom);
+            long timestampNs, int left, int top, int right, int bottom, int transform);
 
     private synchronized native int nativeAttachAndQueueImage(long nativeCtx,
             long imageNativeBuffer, int imageFormat, long timestampNs, int left,
-            int top, int right, int bottom);
+            int top, int right, int bottom, int transform);
 
     private synchronized native void cancelImage(long nativeCtx, Image image);
 
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 8a742b7..ba9056e 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3528,6 +3528,8 @@
 
         private final static int TYPE_YUV = 1;
 
+        private final int mTransform = 0; //Default no transform
+
         @Override
         public int getFormat() {
             throwISEIfImageIsInvalid();
@@ -3547,6 +3549,12 @@
         }
 
         @Override
+        public int getTransform() {
+            throwISEIfImageIsInvalid();
+            return mTransform;
+        }
+
+        @Override
         public long getTimestamp() {
             throwISEIfImageIsInvalid();
             return mTimestamp;
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index f5311764..bfb3ea2 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -45,6 +45,7 @@
 #define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
 #define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID   "mNativeBuffer"
 #define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID       "mTimestamp"
+#define ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID       "mTransform"
 
 #define CONSUMER_BUFFER_USAGE_UNKNOWN              0;
 // ----------------------------------------------------------------------------
@@ -66,6 +67,7 @@
 static struct {
     jfieldID mNativeBuffer;
     jfieldID mTimestamp;
+    jfieldID mTransform;
     jfieldID mPlanes;
 } gSurfaceImageClassInfo;
 
@@ -307,6 +309,12 @@
                         "can't find android/graphics/ImageReader.%s",
                         ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
 
+    gSurfaceImageClassInfo.mTransform = env->GetFieldID(
+            imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID, "I");
+    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTransform == NULL,
+                        "can't find android/graphics/ImageReader.%s",
+                        ANDROID_MEDIA_SURFACEIMAGE_TF_JNI_ID);
+
     gSurfaceImageClassInfo.mPlanes = env->GetFieldID(
             imageClazz, "mPlanes", "[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;");
     LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL,
@@ -596,6 +604,8 @@
     Image_setBufferItem(env, image, buffer);
     env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
             static_cast<jlong>(buffer->mTimestamp));
+    env->SetIntField(image, gSurfaceImageClassInfo.mTransform,
+            static_cast<jint>(buffer->mTransform));
 
     return ACQUIRE_SUCCESS;
 }
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 2c74992..2b8f9f89 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -421,7 +421,7 @@
 }
 
 static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image,
-        jlong timestampNs, jint left, jint top, jint right, jint bottom) {
+        jlong timestampNs, jint left, jint top, jint right, jint bottom, jint transform) {
     ALOGV("%s", __FUNCTION__);
     JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
     if (ctx == NULL || thiz == NULL) {
@@ -465,6 +465,12 @@
         return;
     }
 
+    res = native_window_set_buffers_transform(anw.get(), transform);
+    if (res != OK) {
+        jniThrowRuntimeException(env, "Set transform failed");
+        return;
+    }
+
     // Finally, queue input buffer
     res = anw->queueBuffer(anw.get(), buffer, fenceFd);
     if (res != OK) {
@@ -487,7 +493,7 @@
 
 static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nativeCtx,
         jlong nativeBuffer, jint imageFormat, jlong timestampNs, jint left, jint top,
-        jint right, jint bottom) {
+        jint right, jint bottom, jint transform) {
     ALOGV("%s", __FUNCTION__);
     JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx);
     if (ctx == NULL || thiz == NULL) {
@@ -530,7 +536,7 @@
     }
     sp < ANativeWindow > anw = surface;
 
-    // Step 2. Set timestamp and crop. Note that we do not need unlock the image because
+    // Step 2. Set timestamp, crop and transform. Note that we do not need unlock the image because
     // it was not locked.
     ALOGV("timestamp to be queued: %" PRId64, timestampNs);
     res = native_window_set_buffers_timestamp(anw.get(), timestampNs);
@@ -550,6 +556,12 @@
         return res;
     }
 
+    res = native_window_set_buffers_transform(anw.get(), transform);
+    if (res != OK) {
+        jniThrowRuntimeException(env, "Set transform failed");
+        return res;
+    }
+
     // Step 3. Queue Image.
     res = anw->queueBuffer(anw.get(), buffer->mGraphicBuffer.get(), /*fenceFd*/
             -1);
@@ -785,9 +797,9 @@
     {"nativeInit",              "(Ljava/lang/Object;Landroid/view/Surface;II)J",
                                                               (void*)ImageWriter_init },
     {"nativeClose",              "(J)V",                      (void*)ImageWriter_close },
-    {"nativeAttachAndQueueImage", "(JJIJIIII)I",          (void*)ImageWriter_attachAndQueueImage },
+    {"nativeAttachAndQueueImage", "(JJIJIIIII)I",          (void*)ImageWriter_attachAndQueueImage },
     {"nativeDequeueInputImage", "(JLandroid/media/Image;)V",  (void*)ImageWriter_dequeueImage },
-    {"nativeQueueInputImage",   "(JLandroid/media/Image;JIIII)V",  (void*)ImageWriter_queueImage },
+    {"nativeQueueInputImage",   "(JLandroid/media/Image;JIIIII)V",  (void*)ImageWriter_queueImage },
     {"cancelImage",             "(JLandroid/media/Image;)V",   (void*)ImageWriter_cancelImage },
 };
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index e8f5282..6e12e20 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -15,6 +15,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
 
 import java.util.List;
 
@@ -53,7 +54,7 @@
             if (connected) {
                 WifiInfo info = mWifiManager.getConnectionInfo();
                 if (info != null) {
-                    ssid = getSsid(info);
+                    ssid = getValidSsid(info);
                 } else {
                     ssid = null;
                 }
@@ -67,9 +68,9 @@
         }
     }
 
-    private String getSsid(WifiInfo info) {
+    private String getValidSsid(WifiInfo info) {
         String ssid = info.getSSID();
-        if (ssid != null) {
+        if (ssid != null && !WifiSsid.NONE.equals(ssid)) {
             return ssid;
         }
         // OK, it's not in the connectionInfo; we have to go hunting for it
diff --git a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml b/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
index 382d9d5..726d814 100644
--- a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
@@ -14,16 +14,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="14dp"
+        android:height="24dp"
+        android:viewportWidth="14"
+        android:viewportHeight="24">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M4,7h4v10H6V9H4V7z M15.83,11.72L18.66,7h-2.33l-1.66,2.77L13,7h-2.33l2.83,4.72L10.33,17h2.33l2-3.34l2,3.34H19 L15.83,11.72z" />
+        android:pathData="M5.62,16.29H4.58V9.06l-1.79,0.8V8.88l2.67-1.17h0.16V16.29z" />
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M11.08,11.02l1.61-3.27h1.26l-2.22,4.23l2.27,4.3h-1.27l-1.64-3.33l-1.65,3.33H8.16l2.28-4.3L8.21,7.75h1.25L11.08,11.02z" />
     <path
-        android:pathData="M0,0h24v24H0V0z" />
-</vector>
+        android:pathData="M 0 0 H 13.99 V 24 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
index ce003e4..7a539ff 100644
--- a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
@@ -14,16 +14,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="14dp"
+        android:height="24dp"
+        android:viewportWidth="14"
+        android:viewportHeight="24">
 
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M3.83,11.38h0.66c0.43,0,0.75-0.13,0.98-0.39s0.35-0.62,0.35-1.07c0-1-0.39-1.5-1.16-1.5c-0.37,0-0.66,0.13-0.87,0.4 S3.47,9.44,3.47,9.88H2.44c0-0.68,0.21-1.25,0.62-1.69s0.95-0.67,1.6-0.67c0.67,0,1.21,0.21,1.6,0.63s0.59,1.01,0.59,1.78 c0,0.39-0.1,0.76-0.31,1.1s-0.47,0.59-0.8,0.75c0.8,0.3,1.21,0.96,1.21,2c0,0.76-0.21,1.37-0.64,1.82s-0.98,0.68-1.66,0.68 c-0.68,0-1.22-0.21-1.64-0.64s-0.62-1-0.62-1.73h1.04c0,0.45,0.11,0.81,0.33,1.08s0.52,0.4,0.9,0.4c0.39,0,0.69-0.13,0.92-0.39 s0.34-0.66,0.34-1.2c0-1.04-0.49-1.55-1.47-1.55H3.83V11.38z" />
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M3,7v2h5v2H4v2h4v2H3v2h5c1.1,0,2-0.9,2-2v-1.5c0-0.83-0.67-1.5-1.5-1.5c0.83,0,1.5-0.67,1.5-1.5V9c0-1.1-0.9-2-2-2H3z M21,11v4c0,1.1-0.9,2-2,2h-5c-1.1,0-2-0.9-2-2V9c0-1.1,0.9-2,2-2h5c1.1,0,2,0.9,2,2h-2h-5v6h5v-2h-2.5v-2H21z" />
-</vector>
+        android:pathData="M14,15.11l-0.19,0.23c-0.54,0.63-1.33,0.94-2.37,0.94c-0.92,0-1.65-0.31-2.17-0.92s-0.79-1.48-0.81-2.59V11.1 c0-1.2,0.24-2.09,0.72-2.69s1.19-0.89,2.15-0.89c0.81,0,1.45,0.23,1.91,0.68s0.71,1.1,0.76,1.94h-1.07 c-0.04-0.53-0.19-0.95-0.44-1.25s-0.63-0.45-1.15-0.45c-0.61,0-1.06,0.2-1.35,0.6s-0.43,1.04-0.45,1.92v1.74 c0,0.86,0.16,1.52,0.49,1.98s0.8,0.69,1.41,0.69c0.58,0,1.02-0.14,1.32-0.42l0.16-0.15v-1.96h-1.56v-0.92H14V15.11z" />
+    <path
+        android:pathData="M 0 0 H 14 V 24 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
index 8e22e06..b2fab0c8 100644
--- a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
@@ -14,16 +14,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="14dp"
+        android:height="24dp"
+        android:viewportWidth="14"
+        android:viewportHeight="24">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M9,7H7v5H5V7H3v7h4v3h2v-3h2v-2H9V7z M17,11v2h2v2h-5V9h7c0-1.1-0.9-2-2-2h-5c-1.1,0-2,0.9-2,2v6c0,1.1,0.9,2,2,2h5 c1.1,0,2-0.9,2-2v-4H17z" />
+        android:pathData="M6.42,13.3h0.95v0.88H6.42v1.98H5.38v-1.98H2.16v-0.64l3.17-5.91h1.09C6.42,7.63,6.42,13.3,6.42,13.3z M3.31,13.3h2.07 V9.25L3.31,13.3z" />
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M13.99,15.11l-0.19,0.23c-0.54,0.63-1.33,0.94-2.37,0.94c-0.92,0-1.65-0.31-2.17-0.92s-0.79-1.48-0.8-2.59V11.1 c0-1.2,0.24-2.09,0.72-2.69s1.2-0.89,2.15-0.89c0.81,0,1.45,0.23,1.91,0.68s0.71,1.1,0.76,1.94h-1.07 c-0.04-0.53-0.19-0.95-0.44-1.25s-0.63-0.45-1.14-0.45c-0.61,0-1.06,0.2-1.35,0.6s-0.43,1.04-0.45,1.92v1.74 c0,0.86,0.16,1.52,0.49,1.98s0.8,0.69,1.41,0.69c0.58,0,1.02-0.14,1.32-0.42l0.16-0.15v-1.96h-1.56v-0.92h2.62V15.11z" />
     <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:pathData="M 0 0 H 14 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml b/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
index 32add0c..bdbb2df 100644
--- a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
@@ -14,16 +14,20 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="20dp"
+        android:height="24dp"
+        android:viewportWidth="20"
+        android:viewportHeight="24">
 
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M6.18,13.3h0.95v0.88H6.18v1.98H5.14v-1.98H1.92v-0.64l3.17-5.91h1.09V13.3z M3.07,13.3h2.07V9.25L3.07,13.3z" />
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M13,11v2h2v2h-4V9h6c0-1.1-0.9-2-2-2h-4C9.9,7,9,7.9,9,9v6c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2v-4H13z M24,11h-2V9h-2v2h-2v2 h2v2h2v-2h2V11z M7,7H5v5H3V7H1v7h4v3h2v-3h1v-2H7V7z" />
+        android:pathData="M13.75,15.11l-0.19,0.23c-0.54,0.63-1.33,0.94-2.37,0.94c-0.92,0-1.65-0.31-2.17-0.92s-0.79-1.48-0.8-2.59V11.1 c0-1.2,0.24-2.09,0.72-2.69s1.2-0.89,2.15-0.89c0.81,0,1.45,0.23,1.91,0.68s0.71,1.1,0.76,1.94h-1.07 c-0.04-0.53-0.19-0.95-0.44-1.25s-0.63-0.45-1.14-0.45c-0.61,0-1.06,0.2-1.35,0.6s-0.43,1.04-0.45,1.92v1.74 c0,0.86,0.16,1.52,0.49,1.98s0.8,0.69,1.41,0.69c0.58,0,1.02-0.14,1.32-0.42l0.16-0.15v-1.96h-1.56v-0.92h2.63V15.11z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M 20 9.64 L 18 9.64 L 18 7.64 L 17 7.64 L 17 9.64 L 15 9.64 L 15 10.64 L 17 10.64 L 17 12.64 L 18 12.64 L 18 10.64 L 20 10.64 Z" />
+    <path
+        android:pathData="M 0 0 H 20 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml b/packages/SystemUI/res/drawable/ic_e_mobiledata.xml
index 80e507b..1a4a2e3 100644
--- a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_e_mobiledata.xml
@@ -14,16 +14,14 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="7dp"
+        android:height="24dp"
+        android:viewportWidth="7"
+        android:viewportHeight="24">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M 16 9 L 16 7 L 8 7 L 8 17 L 16 17 L 16 15 L 10 15 L 10 13 L 16 13 L 16 11 L 10 11 L 10 9 Z" />
+        android:pathData="M6.5,12.32H3.48v3.02H7v0.92H2.41V7.73h4.53v0.92H3.48v2.75H6.5V12.32z" />
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:pathData="M 0 0 H 7 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml b/packages/SystemUI/res/drawable/ic_g_mobiledata.xml
index 04049ce..d6a0488 100644
--- a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_g_mobiledata.xml
@@ -14,16 +14,14 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="8dp"
+        android:height="24dp"
+        android:viewportWidth="8"
+        android:viewportHeight="24">
 
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
-    <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12,11v2h2v2H9V9h0.44H14h2c0-1.1-0.9-2-2-2H9C7.9,7,7,7.9,7,9v6c0,1.1,0.9,2,2,2h5c1.1,0,2-0.9,2-2v-4H12z" />
+        android:pathData="M8,15.21l-0.19,0.23c-0.54,0.63-1.33,0.94-2.37,0.94c-0.92,0-1.65-0.31-2.17-0.92s-0.79-1.48-0.81-2.59V11.2 c0-1.2,0.24-2.09,0.72-2.69s1.19-0.89,2.15-0.89c0.81,0,1.45,0.23,1.91,0.68S7.95,9.39,8,10.23H6.93C6.88,9.7,6.74,9.28,6.49,8.99 S5.85,8.54,5.34,8.54c-0.61,0-1.06,0.2-1.35,0.6s-0.43,1.04-0.45,1.92v1.74c0,0.86,0.16,1.52,0.49,1.98s0.8,0.69,1.41,0.69 c0.58,0,1.02-0.14,1.32-0.42l0.16-0.15v-1.96H5.37v-0.92H8V15.21z" />
+    <path
+        android:pathData="M 0 0 H 8 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml b/packages/SystemUI/res/drawable/ic_h_mobiledata.xml
index 31cc4a7..be85bbb 100644
--- a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_h_mobiledata.xml
@@ -14,16 +14,14 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="8dp"
+        android:height="24dp"
+        android:viewportWidth="8"
+        android:viewportHeight="24">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M15,11H9V7H7v10h2v-4h6v4h2V7h-2V11z" />
+        android:pathData="M8,16.27H6.92v-3.94H3.49v3.94H2.42V7.73h1.07v3.67h3.43V7.73H8V16.27z" />
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:pathData="M 0 0 H 8 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml b/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
index ca1020e..f31f83c 100644
--- a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
@@ -14,19 +14,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="14dp"
+        android:height="24dp"
+        android:viewportWidth="14"
+        android:viewportHeight="24">
 
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7.64,16.27H6.56v-3.94H3.13v3.94H2.06V7.73h1.07v3.67h3.43V7.73h1.08V16.27z" />
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12,11H6V7H4v10h2v-4h6v4h2V7h-2V11z" />
+        android:pathData="M 14 9.73 L 12 9.73 L 12 7.73 L 11 7.73 L 11 9.73 L 9 9.73 L 9 10.73 L 11 10.73 L 11 12.73 L 12 12.73 L 12 10.73 L 14 10.73 Z" />
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M22,11h-2V9h-2v2h-2v2h2v2h2v-2h2V11z" />
+        android:pathData="M 0 0 H 14 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml b/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
index 5d90965..e45b5e0 100644
--- a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
@@ -14,16 +14,20 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="18dp"
+        android:height="24dp"
+        android:viewportWidth="18"
+        android:viewportHeight="24">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M6,14h3v2H4V8h2V14z M9,10h2v6h2v-6h2V8H9V10z M21,10V8h-5v8h2h3v-2h-3v-0.67V13h3v-2h-3v-1H21z" />
+        android:pathData="M3.79,15.35h3.35v0.92H2.71V7.73h1.08V15.35z" />
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.15,8.65H9.91v7.61H8.84V8.65H6.6V7.73h5.55V8.65z" />
     <path
-        android:pathData="M0,0h24v24H0V0z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17.5,12.32h-3.02v3.02H18v0.92h-4.59V7.73h4.53v0.92h-3.46v2.75h3.02V12.32z" />
+    <path
+        android:pathData="M 0 0 H 18 V 24 H 0 V 0 Z" />
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml b/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
index 0366e24..553a5bd 100644
--- a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
+++ b/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
@@ -14,16 +14,23 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M3,14h3v2H1V8h2V14z M5,10h2v6h2v-6h2V8H5V10z M12,16h5v-2h-3v-1h3v-2h-3v-1h3V8h-5V16z M24,11h-2V9h-2v2h-2v2h2v2h2v-2h2 V11z" />
+        android:pathData="M3.91,15.35h3.35v0.92H2.84V7.73h1.08V15.35z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.28,8.65h-2.24v7.61H8.96V8.65H6.73V7.73h5.55V8.65z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17.63,12.32h-3.02v3.02h3.52v0.92h-4.59V7.73h4.53v0.92h-3.46v2.75h3.02V12.32z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M 24 9.76 L 22 9.76 L 22 7.76 L 21 7.76 L 21 9.76 L 19 9.76 L 19 10.76 L 21 10.76 L 21 12.76 L 22 12.76 L 22 10.76 L 24 10.76 Z" />
     <path
         android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:pathData="M0,0h24v24H0V0z" />
 </vector>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index 7500bc6..ea1ad2d1 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -60,7 +60,7 @@
             android:layout_marginEnd="32dp"
             android:gravity="center_vertical|start"
             android:ellipsize="marquee"
-            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textAppearance="@style/TextAppearance.QS.TileLabel"
             android:textColor="?android:attr/textColorPrimary"
             android:textDirection="locale"
             android:singleLine="true" />
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 940c9ef..5fa6c79 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -29,6 +29,8 @@
 
     private IRecentsAnimationController mAnimationController;
 
+    public RecentsAnimationControllerCompat() { }
+
     public RecentsAnimationControllerCompat(IRecentsAnimationController animationController) {
         mAnimationController = animationController;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6098e4e..9d5fb52 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -68,6 +68,7 @@
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
@@ -78,7 +79,6 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import com.google.android.collect.Lists;
@@ -985,6 +985,15 @@
         }
 
         /**
+         * Determine whether the device is plugged in (USB, power).
+         * @return true if the device is plugged in wired (as opposed to wireless)
+         */
+        public boolean isPluggedInWired() {
+            return plugged == BatteryManager.BATTERY_PLUGGED_AC
+                    || plugged == BatteryManager.BATTERY_PLUGGED_USB;
+        }
+
+        /**
          * Whether or not the device is charged. Note that some devices never return 100% for
          * battery level, so this allows either battery level or status to determine if the
          * battery is charged.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 8d99303..ae99786 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -348,7 +348,7 @@
         return ComponentName.unflattenFromString(action);
     }
 
-    public static QSTile create(QSTileHost host, String spec) {
+    public static CustomTile create(QSTileHost host, String spec) {
         if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
             throw new IllegalArgumentException("Bad custom tile spec: " + spec);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 77c3bfa..8d48890 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -52,6 +52,14 @@
     }
 
     public QSTile createTile(String tileSpec) {
+        QSTileImpl tile = createTileInternal(tileSpec);
+        if (tile != null) {
+            tile.handleStale(); // Tile was just created, must be stale.
+        }
+        return tile;
+    }
+
+    private QSTileImpl createTileInternal(String tileSpec) {
         if (tileSpec.equals("wifi")) return new WifiTile(mHost);
         else if (tileSpec.equals("bt")) return new BluetoothTile(mHost);
         else if (tileSpec.equals("cell")) return new CellularTile(mHost);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 24ddafc..40b8d78 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -103,7 +103,6 @@
     protected QSTileImpl(QSHost host) {
         mHost = host;
         mContext = host.getContext();
-        handleStale(); // Tile was just created, must be stale.
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 3b79db7..06183e9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -78,7 +78,6 @@
 
     @Override
     public void handleSetListening(boolean listening) {
-        if (mController == null) return;
         if (listening) {
             mController.addCallback(mCallback);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 678aa71..ed78048 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -83,7 +83,6 @@
 
     @Override
     public void handleSetListening(boolean listening) {
-        if (mController == null) return;
         if (DEBUG) Log.d(TAG, "handleSetListening " + listening);
         if (listening) {
             mController.addCallback(mCallback);
@@ -98,7 +97,6 @@
     @Override
     protected void handleUserSwitch(int newUserId) {
         super.handleUserSwitch(newUserId);
-        if (mController == null) return;
         mController.setCurrentUserId(newUserId);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 8427e32..7dcf5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -259,7 +259,6 @@
     public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
-        if (mController == null) return;
         if (mListening) {
             mController.addCallback(mZenCallback);
             Prefs.registerListener(mContext, mPrefListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 4f4004c..3c565ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -64,7 +64,7 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
-    public static QSTile create(QSHost host, String spec) {
+    public static IntentTile create(QSHost host, String spec) {
         if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
             throw new IllegalArgumentException("Bad intent tile spec: " + spec);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 60422ee..28b047b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -51,7 +51,6 @@
     }
 
     public void handleSetListening(boolean listening) {
-        if (mController == null) return;
         if (listening) {
             mController.addCallback(mCallback);
         } else {
@@ -66,7 +65,6 @@
 
     @Override
     protected void handleClick() {
-        if (mController == null) return;
         final boolean newState = !mState.value;
         mController.setRotationLocked(!newState);
         refreshState(newState);
@@ -79,7 +77,6 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        if (mController == null) return;
         final boolean rotationLocked = mController.isRotationLocked();
 
         state.value = !rotationLocked;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 3ad3940..28fdc11 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -76,7 +76,6 @@
 
     @Override
     public void handleSetListening(boolean listening) {
-        if (mController == null) return;
         if (listening) {
             mController.addCallback(mSignalCallback);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 859dc39..795140e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -92,6 +92,7 @@
     private boolean mVisible;
 
     private boolean mPowerPluggedIn;
+    private boolean mPowerPluggedInWired;
     private boolean mPowerCharged;
     private int mChargingSpeed;
     private int mChargingWattage;
@@ -476,6 +477,7 @@
         pw.println("KeyguardIndicationController:");
         pw.println("  mTransientTextColor: " + Integer.toHexString(mTransientTextColor));
         pw.println("  mInitialTextColor: " + Integer.toHexString(mInitialTextColor));
+        pw.println("  mPowerPluggedInWired: " + mPowerPluggedInWired);
         pw.println("  mPowerPluggedIn: " + mPowerPluggedIn);
         pw.println("  mPowerCharged: " + mPowerCharged);
         pw.println("  mChargingSpeed: " + mChargingSpeed);
@@ -496,12 +498,13 @@
             boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
                     || status.status == BatteryManager.BATTERY_STATUS_FULL;
             boolean wasPluggedIn = mPowerPluggedIn;
+            mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;
             mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
             mPowerCharged = status.isCharged();
             mChargingWattage = status.maxChargingWattage;
             mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
             mBatteryLevel = status.level;
-            updateIndication(!wasPluggedIn && mPowerPluggedIn);
+            updateIndication(!wasPluggedIn && mPowerPluggedInWired);
             if (mDozing) {
                 if (!wasPluggedIn && mPowerPluggedIn) {
                     showTransientIndication(computePowerIndication());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 55a23e3..3cf7741 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -105,7 +105,6 @@
 
     private final int mMobileSignalGroupEndPadding;
     private final int mMobileDataIconStartPadding;
-    private final int mWideTypeIconStartPadding;
     private final int mSecondaryTelephonyPadding;
     private final int mEndPadding;
     private final int mEndPaddingNothingVisible;
@@ -136,7 +135,6 @@
                 res.getDimensionPixelSize(R.dimen.mobile_signal_group_end_padding);
         mMobileDataIconStartPadding =
                 res.getDimensionPixelSize(R.dimen.mobile_data_icon_start_padding);
-        mWideTypeIconStartPadding = res.getDimensionPixelSize(R.dimen.wide_type_icon_start_padding);
         mSecondaryTelephonyPadding = res.getDimensionPixelSize(R.dimen.secondary_telephony_padding);
         mEndPadding = res.getDimensionPixelSize(R.dimen.signal_cluster_battery_padding);
         mEndPaddingNothingVisible = res.getDimensionPixelSize(
@@ -302,7 +300,6 @@
         state.mMobileTypeId = statusType;
         state.mMobileDescription = statusIcon.contentDescription;
         state.mMobileTypeDescription = typeContentDescription;
-        state.mIsMobileTypeIconWide = statusType != 0 && isWide;
         state.mRoaming = roaming;
         state.mActivityIn = activityIn && mActivityEnabled;
         state.mActivityOut = activityOut && mActivityEnabled;
@@ -607,7 +604,6 @@
         private int mMobileStrengthId = 0, mMobileTypeId = 0;
         private int mLastMobileStrengthId = -1;
         private int mLastMobileTypeId = -1;
-        private boolean mIsMobileTypeIconWide;
         private String mMobileDescription, mMobileTypeDescription;
 
         private ViewGroup mMobileGroup;
@@ -661,9 +657,7 @@
             // When this isn't next to wifi, give it some extra padding between the signals.
             mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
                     0, 0, 0);
-            mMobile.setPaddingRelative(
-                    mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
-                    0, 0, 0);
+            mMobile.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0);
 
             if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
                         (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index ae55ae8..739d8d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -158,6 +158,7 @@
 
     private final WakeLock mWakeLock;
     private boolean mWakeLockHeld;
+    private boolean mKeyguardOccluded;
 
     public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
             ScrimView scrimInFront, View headsUpScrim, Consumer<Integer> scrimVisibleListener,
@@ -268,12 +269,13 @@
 
         // AOD wallpapers should fade away after a while
         if (mWallpaperSupportsAmbientMode && mDozeParameters.getAlwaysOn()
-                && (mState == ScrimState.AOD || mState == ScrimState.PULSING)) {
+                && mState == ScrimState.AOD) {
             if (!mWallpaperVisibilityTimedOut) {
                 mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(),
                         AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
             }
-        } else {
+        // Do not re-schedule timeout when pulsing, let's save some extra battery.
+        } else if (mState != ScrimState.PULSING) {
             mTimeTicker.cancel();
             mWallpaperVisibilityTimedOut = false;
         }
@@ -317,7 +319,7 @@
 
     @VisibleForTesting
     protected void onHideWallpaperTimeout() {
-        if (mState != ScrimState.AOD && mState != ScrimState.PULSING) {
+        if (mState != ScrimState.AOD) {
             return;
         }
 
@@ -478,11 +480,13 @@
             mLightBarController.setScrimColor(mScrimInFront.getColors());
         }
 
-        // We want to override the back scrim opacity for AOD and PULSING
+        // We want to override the back scrim opacity for the AOD state
         // when it's time to fade the wallpaper away.
-        boolean overrideBackScrimAlpha = (mState == ScrimState.PULSING || mState == ScrimState.AOD)
-                && mWallpaperVisibilityTimedOut;
-        if (overrideBackScrimAlpha) {
+        boolean aodWallpaperTimeout = mState == ScrimState.AOD && mWallpaperVisibilityTimedOut;
+        // We also want to hide FLAG_SHOW_WHEN_LOCKED activities under the scrim.
+        boolean occludedKeyguard = (mState == ScrimState.PULSING || mState == ScrimState.AOD)
+                && mKeyguardOccluded;
+        if (aodWallpaperTimeout || occludedKeyguard) {
             mCurrentBehindAlpha = 1;
         }
 
@@ -926,6 +930,10 @@
         mExpansionAffectsAlpha = expansionAffectsAlpha;
     }
 
+    public void setKeyguardOccluded(boolean keyguardOccluded) {
+        mKeyguardOccluded = keyguardOccluded;
+    }
+
     public interface Callback {
         default void onStart() {
         }
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 c92f300..7422a43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2040,6 +2040,7 @@
 
     public void setOccluded(boolean occluded) {
         mIsOccluded = occluded;
+        mScrimController.setKeyguardOccluded(occluded);
         updateHideIconsForBouncer(false /* animate */);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 779b0fb..4533aa5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -198,7 +198,7 @@
             }
         });
         mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
-                mCallbackHandler, this);
+                mCallbackHandler, this, mWifiManager);
 
         mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index b4c3eca..0f65421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -43,10 +43,11 @@
     private final WifiStatusTracker mWifiTracker;
 
     public WifiSignalController(Context context, boolean hasMobileData,
-            CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
+            CallbackHandler callbackHandler, NetworkControllerImpl networkController,
+            WifiManager wifiManager) {
         super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
                 callbackHandler, networkController);
-        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mWifiManager = wifiManager;
         mWifiTracker = new WifiStatusTracker(mWifiManager);
         mHasMobileData = hasMobileData;
         Handler handler = new WifiHandler(Looper.getMainLooper());
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 14d5c6f5..fc932c3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -41,7 +41,7 @@
     @VisibleForTesting
     static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
-        NotificationChannel batteryChannel = new NotificationChannel(BATTERY,
+        final NotificationChannel batteryChannel = new NotificationChannel(BATTERY,
                 context.getString(R.string.notification_channel_battery),
                 NotificationManager.IMPORTANCE_MAX);
         final String soundPath = Settings.Global.getString(context.getContentResolver(),
@@ -50,22 +50,33 @@
                 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                 .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT)
                 .build());
+        batteryChannel.setBlockableSystem(true);
+        batteryChannel.setBypassDnd(true);
+
+        final NotificationChannel alerts = new NotificationChannel(
+                ALERTS,
+                context.getString(R.string.notification_channel_alerts),
+                NotificationManager.IMPORTANCE_HIGH);
+        alerts.setBypassDnd(true);
+
+        final NotificationChannel general = new NotificationChannel(
+                GENERAL,
+                context.getString(R.string.notification_channel_general),
+                NotificationManager.IMPORTANCE_MIN);
+        general.setBypassDnd(true);
+
+        final NotificationChannel storage = new NotificationChannel(
+                STORAGE,
+                context.getString(R.string.notification_channel_storage),
+                isTv(context)
+                        ? NotificationManager.IMPORTANCE_DEFAULT
+                        : NotificationManager.IMPORTANCE_LOW);
+        storage.setBypassDnd(true);
 
         nm.createNotificationChannels(Arrays.asList(
-                new NotificationChannel(
-                        ALERTS,
-                        context.getString(R.string.notification_channel_alerts),
-                        NotificationManager.IMPORTANCE_HIGH),
-                new NotificationChannel(
-                        GENERAL,
-                        context.getString(R.string.notification_channel_general),
-                        NotificationManager.IMPORTANCE_MIN),
-                new NotificationChannel(
-                        STORAGE,
-                        context.getString(R.string.notification_channel_storage),
-                        isTv(context)
-                                ? NotificationManager.IMPORTANCE_DEFAULT
-                                : NotificationManager.IMPORTANCE_LOW),
+                alerts,
+                general,
+                storage,
                 createScreenshotChannel(
                         context.getString(R.string.notification_channel_screenshot),
                         nm.getNotificationChannel(SCREENSHOTS_LEGACY)),
@@ -101,6 +112,8 @@
 
         screenshotChannel.setSound(Uri.parse(""), // silent
                 new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
+        screenshotChannel.setBypassDnd(true);
+        screenshotChannel.setBlockableSystem(true);
 
         if (legacySS != null) {
             // Respect any user modified fields from the old channel.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index f088c0b..d32c9a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -475,6 +475,19 @@
         Assert.assertTrue("Should be focusable on keyguard", mScrimInFront.isFocusable());
     }
 
+    @Test
+    public void testHidesShowWhenLockedActivity() {
+        mScrimController.setWallpaperSupportsAmbientMode(true);
+        mScrimController.setKeyguardOccluded(true);
+        mScrimController.transitionTo(ScrimState.AOD);
+        mScrimController.finishAnimationsImmediately();
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+
+        mScrimController.transitionTo(ScrimState.PULSING);
+        mScrimController.finishAnimationsImmediately();
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+    }
+
     /**
      * Conserves old notification density after leaving state and coming back.
      *
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 14baaeb..f13fa4e 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
@@ -30,6 +30,7 @@
 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.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -547,6 +548,16 @@
         verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any());
     }
 
+    @Test
+    public void testSetOccluded_propagatesToScrimController() {
+        mStatusBar.setOccluded(true);
+        verify(mScrimController).setKeyguardOccluded(eq(true));
+
+        reset(mScrimController);
+        mStatusBar.setOccluded(false);
+        verify(mScrimController).setKeyguardOccluded(eq(false));
+    }
+
     static class TestableStatusBar extends StatusBar {
         public TestableStatusBar(StatusBarKeyguardViewManager man,
                 UnlockMethodCache unlock, KeyguardIndicationController key,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 30c7b53..fc3de84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -5,6 +5,7 @@
 import android.net.NetworkInfo;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -21,6 +22,7 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.when;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -143,10 +145,11 @@
     protected void setWifiState(boolean connected, String ssid) {
         Intent i = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class);
-        Mockito.when(networkInfo.isConnected()).thenReturn(connected);
+        when(networkInfo.isConnected()).thenReturn(connected);
 
-        //TODO(b/69974497) mock of mWifiManager.getConnectionInfo() needed
-        // Mockito.when(wifiInfo.getSSID()).thenReturn(ssid);
+        WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
+        when(wifiInfo.getSSID()).thenReturn(ssid);
+        when(mMockWm.getConnectionInfo()).thenReturn(wifiInfo);
 
         i.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
         mNetworkController.onReceive(mContext, i);
@@ -175,8 +178,7 @@
         assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue());
         assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
         assertEquals("WiFi signal, in quick settings", icon, iconState.icon);
-        // TODO(b/69974497) Need to mock mWifiManager.getConnectionInfo() to supply the ssid.
-        // assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue());
+        assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue());
     }
 
     protected void verifyLastWifiIcon(boolean visible, int icon) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b911c7b..1db373d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -593,7 +593,7 @@
         out.startDocument(null, true);
         out.startTag(null, TAG_NOTIFICATION_POLICY);
         out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
-        mZenModeHelper.writeXml(out, forBackup);
+        mZenModeHelper.writeXml(out, forBackup, null);
         mRankingHelper.writeXml(out, forBackup);
         mListeners.writeXml(out, forBackup);
         mAssistants.writeXml(out, forBackup);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index e862530..5c82343 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -56,6 +56,7 @@
 import android.service.notification.ZenModeConfig.ZenRule;
 import android.service.notification.ZenModeProto;
 import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -234,25 +235,12 @@
             config = mDefaultConfig.copy();
             config.user = user;
         }
-        enforceDefaultRulesExist(config);
         synchronized (mConfig) {
             setConfigLocked(config, reason);
         }
         cleanUpZenRules();
     }
 
-    private void enforceDefaultRulesExist(ZenModeConfig config) {
-        for (String id : ZenModeConfig.DEFAULT_RULE_IDS) {
-            if (!config.automaticRules.containsKey(id)) {
-                if (id.equals(ZenModeConfig.EVENTS_DEFAULT_RULE_ID)) {
-                    appendDefaultEventRules(config);
-                } else if (id.equals(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID)) {
-                    appendDefaultEveryNightRule(config);
-                }
-            }
-        }
-    }
-
     public int getZenModeListenerInterruptionFilter() {
         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
     }
@@ -623,43 +611,59 @@
 
     public void readXml(XmlPullParser parser, boolean forRestore)
             throws XmlPullParserException, IOException {
-        final ZenModeConfig config = ZenModeConfig.readXml(parser);
+        ZenModeConfig config = ZenModeConfig.readXml(parser);
+        String reason = "readXml";
+
         if (config != null) {
-            if (config.version < ZenModeConfig.XML_VERSION || forRestore) {
-                Settings.Global.putInt(mContext.getContentResolver(),
-                        Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
-            }
             if (forRestore) {
                 //TODO: http://b/22388012
                 if (config.user != UserHandle.USER_SYSTEM) {
                     return;
                 }
                 config.manualRule = null;  // don't restore the manual rule
-                long time = System.currentTimeMillis();
-                if (config.automaticRules != null) {
-                    for (ZenRule automaticRule : config.automaticRules.values()) {
+            }
+
+            boolean resetToDefaultRules = true;
+            long time = System.currentTimeMillis();
+            if (config.automaticRules != null && config.automaticRules.size() > 0) {
+                for (ZenRule automaticRule : config.automaticRules.values()) {
+                    if (forRestore) {
                         // don't restore transient state from restored automatic rules
                         automaticRule.snoozing = false;
                         automaticRule.condition = null;
                         automaticRule.creationTime = time;
                     }
+                    resetToDefaultRules &= !automaticRule.enabled;
                 }
             }
-            if (DEBUG) Log.d(TAG, "readXml");
+
+            if (config.version < ZenModeConfig.XML_VERSION || forRestore) {
+                Settings.Global.putInt(mContext.getContentResolver(),
+                        Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
+
+                // resets zen automatic rules to default
+                // if all prev auto rules were disabled on update
+                if (resetToDefaultRules) {
+                    config.automaticRules = new ArrayMap<>();
+                    appendDefaultRules(config);
+                    reason += ", reset to default rules";
+                }
+            }
+            if (DEBUG) Log.d(TAG, reason);
             synchronized (mConfig) {
-                setConfigLocked(config, "readXml");
+                setConfigLocked(config, reason);
             }
         }
     }
 
-    public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
+    public void writeXml(XmlSerializer out, boolean forBackup, Integer version) throws IOException {
         final int N = mConfigs.size();
         for (int i = 0; i < N; i++) {
             //TODO: http://b/22388012
             if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
                 continue;
             }
-            mConfigs.valueAt(i).writeXml(out);
+            mConfigs.valueAt(i).writeXml(out, version);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3cdb130..6cd60e6a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -660,6 +660,7 @@
     static final Rect mTmpStableFrame = new Rect();
     static final Rect mTmpNavigationFrame = new Rect();
     static final Rect mTmpOutsetFrame = new Rect();
+    private static final Rect mTmpDisplayCutoutSafeExceptMaybeBarsRect = new Rect();
     private static final Rect mTmpRect = new Rect();
 
     WindowState mTopFullscreenOpaqueWindowState;
@@ -4636,7 +4637,8 @@
 
             w.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, df /* overlayFrame */,
                     df /* contentFrame */, df /* visibleFrame */, dcf /* decorFrame */,
-                    df /* stableFrame */, df /* outsetFrame */, displayFrames.mDisplayCutout);
+                    df /* stableFrame */, df /* outsetFrame */, displayFrames.mDisplayCutout,
+                    false /* parentFrameWasClippedByDisplayCutout */);
             final Rect frame = w.getFrameLw();
 
             if (frame.left <= 0 && frame.top <= 0) {
@@ -4699,7 +4701,7 @@
         mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */,
                 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */,
                 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */,
-                displayFrames.mDisplayCutout);
+                displayFrames.mDisplayCutout, false /* parentFrameWasClippedByDisplayCutout */);
 
         // For layout, the status bar is always at the top with our fixed height.
         displayFrames.mStable.top = displayFrames.mUnrestricted.top
@@ -4844,7 +4846,7 @@
         mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
                 mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe, mTmpNavigationFrame, dcf,
                 mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe,
-                displayFrames.mDisplayCutout);
+                displayFrames.mDisplayCutout, false /* parentFrameWasClippedByDisplayCutout */);
         mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
 
         if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
@@ -5299,10 +5301,10 @@
                         vf.set(cf);
                     }
                 }
-                pf.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
             }
         }
 
+        boolean parentFrameWasClippedByDisplayCutout = false;
         final int cutoutMode = attrs.layoutInDisplayCutoutMode;
         final boolean attachedInParent = attached != null && !layoutInScreen;
         final boolean requestedHideNavigation =
@@ -5310,7 +5312,7 @@
         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
         // the cutout safe zone.
         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
-            final Rect displayCutoutSafeExceptMaybeBars = mTmpRect;
+            final Rect displayCutoutSafeExceptMaybeBars = mTmpDisplayCutoutSafeExceptMaybeBarsRect;
             displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
             if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
                     && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
@@ -5339,10 +5341,12 @@
                 // The IME can always extend under the bottom cutout if the navbar is there.
                 displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
             }
-            // Windows that are attached to a parent and laid out in said parent are already
-            // avoidingthe cutout according to that parent and don't need to be further constrained.
+            // Windows that are attached to a parent and laid out in said parent already avoid
+            // the cutout according to that parent and don't need to be further constrained.
             if (!attachedInParent) {
+                mTmpRect.set(pf);
                 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
+                parentFrameWasClippedByDisplayCutout |= !mTmpRect.equals(pf);
             }
             // Make sure that NO_LIMITS windows clipped to the display don't extend under the
             // cutout.
@@ -5400,7 +5404,8 @@
                 + " sf=" + sf.toShortString()
                 + " osf=" + (osf == null ? "null" : osf.toShortString()));
 
-        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout);
+        win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout,
+                parentFrameWasClippedByDisplayCutout);
 
         // Dock windows carve out the bottom of the screen, so normal windows
         // can't appear underneath them.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 9904216..6674e18 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -220,10 +220,13 @@
          * @param outsetFrame The frame that includes areas that aren't part of the surface but we
          * want to treat them as such.
          * @param displayCutout the display cutout
+         * @param parentFrameWasClippedByDisplayCutout true if the parent frame would have been
+         * different if there was no display cutout.
          */
         public void computeFrameLw(Rect parentFrame, Rect displayFrame,
                 Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame,
-                Rect stableFrame, @Nullable Rect outsetFrame, WmDisplayCutout displayCutout);
+                Rect stableFrame, @Nullable Rect outsetFrame, WmDisplayCutout displayCutout,
+                boolean parentFrameWasClippedByDisplayCutout);
 
         /**
          * Retrieve the current frame of the window that has been assigned by
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index b00e595..9b787de 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -159,6 +159,7 @@
         channel.enableVibration(false);
         channel.setBlockableSystem(true);
         channel.setGroup(sChannelGroup.getId());
+        channel.setBypassDnd(true);
         mNotificationManager.createNotificationChannel(channel);
     }
 
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index ad2fabb..235f63e 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -29,6 +29,7 @@
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.os.IBinder;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
@@ -268,15 +269,23 @@
                     .build();
 
             // capture a screenshot into the surface we just created
-            Surface sur = new Surface();
-            sur.copyFrom(mSurfaceControl);
             // TODO(multidisplay): we should use the proper display
-            SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
-                            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), sur);
-            t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
-            t.setAlpha(mSurfaceControl, 0);
-            t.show(mSurfaceControl);
-            sur.destroy();
+            final int displayId = SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN;
+            final IBinder displayHandle = SurfaceControl.getBuiltInDisplay(displayId);
+            // This null check below is to guard a race condition where WMS didn't have a chance to
+            // respond to display disconnection before handling rotation , that surfaceflinger may
+            // return a null handle here because it doesn't think that display is valid anymore.
+            if (displayHandle != null) {
+                Surface sur = new Surface();
+                sur.copyFrom(mSurfaceControl);
+                SurfaceControl.screenshot(displayHandle, sur);
+                t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
+                t.setAlpha(mSurfaceControl, 0);
+                t.show(mSurfaceControl);
+                sur.destroy();
+            } else {
+                Slog.w(TAG, "Built-in display " + displayId + " is null.");
+            }
         } catch (OutOfResourcesException e) {
             Slog.w(TAG, "Unable to allocate freeze surface", e);
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5912897..c100511 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -24,7 +24,6 @@
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.SurfaceControl.Transaction;
-import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
@@ -35,7 +34,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -46,7 +44,6 @@
 import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -410,6 +407,9 @@
 
     private final Rect mParentFrame = new Rect();
 
+    /** Whether the parent frame would have been different if there was no display cutout. */
+    private boolean mParentFrameWasClippedByDisplayCutout;
+
     // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
     // screen area of the device.
     final Rect mDisplayFrame = new Rect();
@@ -839,7 +839,8 @@
     @Override
     public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overscanFrame,
             Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
-            Rect outsetFrame, WmDisplayCutout displayCutout) {
+            Rect outsetFrame, WmDisplayCutout displayCutout,
+            boolean parentFrameWasClippedByDisplayCutout) {
         if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
             // This window is being replaced and either already got information that it's being
             // removed or we are still waiting for some information. Because of this we don't
@@ -848,6 +849,7 @@
             return;
         }
         mHaveFrame = true;
+        mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;
 
         final Task task = getTask();
         final boolean inFullscreenContainer = inFullscreenContainer();
@@ -3055,23 +3057,31 @@
             // Only windows with an AppWindowToken are letterboxed.
             return false;
         }
-        if (getDisplayContent().getDisplayInfo().displayCutout == null) {
-            // No cutout, no letterbox.
+        if (!mParentFrameWasClippedByDisplayCutout) {
+            // Cutout didn't make a difference, no letterbox
             return false;
         }
         if (mAttrs.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
             // Layout in cutout, no letterbox.
             return false;
         }
-        // TODO: handle dialogs and other non-filling windows
-        if (mAttrs.layoutInDisplayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) {
-            // Never layout in cutout, always letterbox.
-            return true;
+        if (!mAttrs.isFullscreen()) {
+            // Not filling the parent frame, no letterbox
+            return false;
         }
-        // Letterbox if any fullscreen mode is set.
-        final int fl = mAttrs.flags;
-        final int sysui = mSystemUiVisibility;
-        return (fl & FLAG_FULLSCREEN) != 0 || (sysui & (SYSTEM_UI_FLAG_FULLSCREEN)) != 0;
+        // Otherwise we need a letterbox if the layout was smaller than the app window token allowed
+        // it to be.
+        return !frameCoversEntireAppTokenBounds();
+    }
+
+    /**
+     * @return true if this window covers the entire bounds of its app window token
+     * @throws NullPointerException if there is no app window token for this window
+     */
+    private boolean frameCoversEntireAppTokenBounds() {
+        mTmpRect.set(mAppToken.getBounds());
+        mTmpRect.intersectUnchecked(mFrame);
+        return mAppToken.getBounds().equals(mTmpRect);
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
index f3539fe..56ba047 100644
--- a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
+++ b/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
@@ -63,7 +63,8 @@
     @Override
     public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overlayFrame,
             Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame,
-            @Nullable Rect outsetFrame, WmDisplayCutout displayCutout) {
+            @Nullable Rect outsetFrame, WmDisplayCutout displayCutout,
+            boolean parentFrameWasClippedByDisplayCutout) {
         this.parentFrame.set(parentFrame);
         this.displayFrame.set(displayFrame);
         this.overscanFrame.set(overlayFrame);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index bd212a9..4638635 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -160,7 +160,7 @@
         // When mFrame extends past cf, the content insets are
         // the difference between mFrame and ContentFrame. Visible
         // and stable frames work the same way.
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame,0, 0, 1000, 1000);
         assertRect(w.mContentInsets, 0, topContentInset, 0, bottomContentInset);
         assertRect(w.mVisibleInsets, 0, topVisibleInset, 0, bottomVisibleInset);
@@ -175,7 +175,7 @@
         w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
         w.mRequestedWidth = 100;
         w.mRequestedHeight = 100;
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 100, 100, 200, 200);
         assertRect(w.mContentInsets, 0, 0, 0, 0);
         // In this case the frames are shrunk to the window frame.
@@ -196,7 +196,7 @@
 
         // Here the window has FILL_PARENT, FILL_PARENT
         // so we expect it to fill the entire available frame.
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 0, 0, 1000, 1000);
 
         // It can select various widths and heights within the bounds.
@@ -204,14 +204,14 @@
         // and we use mRequestedWidth/mRequestedHeight
         w.mAttrs.width = 300;
         w.mAttrs.height = 300;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         // Explicit width and height without requested width/height
         // gets us nothing.
         assertRect(w.mFrame, 0, 0, 0, 0);
 
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         // With requestedWidth/Height we can freely choose our size within the
         // parent bounds.
         assertRect(w.mFrame, 0, 0, 300, 300);
@@ -224,14 +224,14 @@
         w.mRequestedWidth = -1;
         w.mAttrs.width = 100;
         w.mAttrs.height = 100;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 0, 0, 100, 100);
         w.mAttrs.flags = 0;
 
         // But sizes too large will be clipped to the containing frame
         w.mRequestedWidth = 1200;
         w.mRequestedHeight = 1200;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 0, 0, 1000, 1000);
 
         // Before they are clipped though windows will be shifted
@@ -239,7 +239,7 @@
         w.mAttrs.y = 300;
         w.mRequestedWidth = 1000;
         w.mRequestedHeight = 1000;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 0, 0, 1000, 1000);
 
         // If there is room to move around in the parent frame the window will be shifted according
@@ -249,16 +249,16 @@
         w.mRequestedWidth = 300;
         w.mRequestedHeight = 300;
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 700, 0, 1000, 300);
         w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 700, 700, 1000, 1000);
         // Window specified  x and y are interpreted as offsets in the opposite
         // direction of gravity
         w.mAttrs.x = 100;
         w.mAttrs.y = 100;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, 600, 600, 900, 900);
     }
 
@@ -279,7 +279,7 @@
         w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
 
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, null, WmDisplayCutout.NO_CUTOUT, false);
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
         assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
@@ -291,7 +291,7 @@
         final int cfRight = logicalWidth / 2;
         final int cfBottom = logicalHeight / 2;
         final Rect cf = new Rect(0, 0, cfRight, cfBottom);
-        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
         int contentInsetRight = taskRight - cfRight;
         int contentInsetBottom = taskBottom - cfBottom;
@@ -308,7 +308,7 @@
         final int insetRight = insetLeft + (taskRight - taskLeft);
         final int insetBottom = insetTop + (taskBottom - taskTop);
         task.mInsetBounds.set(insetLeft, insetTop, insetRight, insetBottom);
-        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, cf, cf, pf, cf, null, WmDisplayCutout.NO_CUTOUT, false);
         assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
         contentInsetRight = insetRight - cfRight;
         contentInsetBottom = insetBottom - cfBottom;
@@ -340,13 +340,13 @@
 
         final Rect policyCrop = new Rect();
 
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
         w.calculatePolicyCrop(policyCrop);
         assertRect(policyCrop, 0, cf.top, logicalWidth, cf.bottom);
 
         dcf.setEmpty();
         // Likewise with no decor frame we would get no crop
-        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null, WmDisplayCutout.NO_CUTOUT, false);
         w.calculatePolicyCrop(policyCrop);
         assertRect(policyCrop, 0, 0, logicalWidth, logicalHeight);
 
@@ -359,7 +359,7 @@
         w.mAttrs.height = logicalHeight / 2;
         w.mRequestedWidth = logicalWidth / 2;
         w.mRequestedHeight = logicalHeight / 2;
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, WmDisplayCutout.NO_CUTOUT, false);
 
         w.calculatePolicyCrop(policyCrop);
         // Normally the crop is shrunk from the decor frame
@@ -396,7 +396,7 @@
         final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
         w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
                 pf /* contentFrame */, pf /* visibleFrame */, pf /* decorFrame */,
-                pf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT);
+                pf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT, false);
         // For non fullscreen tasks the containing frame is based off the
         // task bounds not the parent frame.
         assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
@@ -415,7 +415,7 @@
 
         w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
                 cf /* contentFrame */, cf /* visibleFrame */, pf /* decorFrame */,
-                cf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT);
+                cf /* stableFrame */, null /* outsetFrame */, WmDisplayCutout.NO_CUTOUT, false);
         assertEquals(cf, w.mFrame);
         assertEquals(cf, w.getContentFrameLw());
         assertRect(w.mContentInsets, 0, 0, 0, 0);
@@ -433,7 +433,7 @@
         final WmDisplayCutout cutout = WmDisplayCutout.computeSafeInsets(
                 fromBoundingRect(500, 0, 550, 50), pf.width(), pf.height());
 
-        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, cutout);
+        w.computeFrameLw(pf, pf, pf, pf, pf, pf, pf, pf, cutout, false);
 
         assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetTop(), 50);
         assertEquals(w.mDisplayCutout.getDisplayCutout().getSafeInsetBottom(), 0);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index be58fd2..381e04c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -49,9 +49,11 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ScheduleInfo;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.util.ArrayMap;
 import android.util.Xml;
 
 import com.android.internal.R;
@@ -102,13 +104,13 @@
                 mConditionProviders));
     }
 
-    private ByteArrayOutputStream writeXmlAndPurge(boolean forBackup)
+    private ByteArrayOutputStream writeXmlAndPurge(boolean forBackup, Integer version)
             throws Exception {
         XmlSerializer serializer = new FastXmlSerializer();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
         serializer.startDocument(null, true);
-        mZenModeHelperSpy.writeXml(serializer, forBackup);
+        mZenModeHelperSpy.writeXml(serializer, forBackup, version);
         serializer.endDocument();
         serializer.flush();
         mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml");
@@ -603,7 +605,7 @@
 
         ZenModeConfig expected = mZenModeHelperSpy.mConfig.copy();
 
-        ByteArrayOutputStream baos = writeXmlAndPurge(false);
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, null);
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), null);
@@ -614,6 +616,96 @@
     }
 
     @Test
+    public void testReadXml() throws Exception {
+        setupZenConfig();
+
+        // automatic zen rule is enabled on upgrade so rules should not be overriden by default
+        ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo weeknights = new ScheduleInfo();
+        customRule.enabled = true;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
+        enabledAutoRule.put("customRule", customRule);
+        mZenModeHelperSpy.mConfig.automaticRules = enabledAutoRule;
+
+        ZenModeConfig expected = mZenModeHelperSpy.mConfig.copy();
+
+        // set previous version
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertTrue(mZenModeHelperSpy.mConfig.automaticRules.containsKey("customRule"));
+        setupZenConfigMaintained();
+    }
+
+    @Test
+    public void testReadXmlResetDefaultRules() throws Exception {
+        setupZenConfig();
+
+        // no enabled automatic zen rule, so rules should be overriden by default rules
+        mZenModeHelperSpy.mConfig.automaticRules = new ArrayMap<>();
+
+        // set previous version
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        // check default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
+        assertTrue(rules.size() != 0);
+        for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
+            assertTrue(rules.containsKey(defaultId));
+        }
+
+        setupZenConfigMaintained();
+    }
+
+
+    @Test
+    public void testReadXmlAllDisabledRulesResetDefaultRules() throws Exception {
+        setupZenConfig();
+
+        // all automatic zen rules are diabled on upgrade so rules should be overriden by default
+        // rules
+        ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
+        ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
+        final ScheduleInfo weeknights = new ScheduleInfo();
+        customRule.enabled = false;
+        customRule.name = "Custom Rule";
+        customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
+        enabledAutoRule.put("customRule", customRule);
+        mZenModeHelperSpy.mConfig.automaticRules = enabledAutoRule;
+
+        // set previous version
+        ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        // check default rules
+        ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
+        assertTrue(rules.size() != 0);
+        for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
+            assertTrue(rules.containsKey(defaultId));
+        }
+        assertFalse(rules.containsKey("customRule"));
+
+        setupZenConfigMaintained();
+    }
+
+    @Test
     public void testPolicyReadsSuppressedEffects() {
         mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
         mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
@@ -622,4 +714,40 @@
         NotificationManager.Policy policy = mZenModeHelperSpy.getNotificationPolicy();
         assertEquals(SUPPRESSED_EFFECT_BADGE, policy.suppressedVisualEffects);
     }
+
+    private void setupZenConfig() {
+        mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        mZenModeHelperSpy.mConfig.allowAlarms = false;
+        mZenModeHelperSpy.mConfig.allowMedia = false;
+        mZenModeHelperSpy.mConfig.allowSystem = false;
+        mZenModeHelperSpy.mConfig.allowReminders = true;
+        mZenModeHelperSpy.mConfig.allowCalls = true;
+        mZenModeHelperSpy.mConfig.allowMessages = true;
+        mZenModeHelperSpy.mConfig.allowEvents = true;
+        mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
+        mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
+        mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
+        mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
+        mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
+        mZenModeHelperSpy.mConfig.manualRule.zenMode =
+                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
+        mZenModeHelperSpy.mConfig.manualRule.enabled = true;
+        mZenModeHelperSpy.mConfig.manualRule.snoozing = true;
+    }
+
+    private void setupZenConfigMaintained() {
+        // config is still the same as when it was setup (setupZenConfig)
+        assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
+        assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
+        assertFalse(mZenModeHelperSpy.mConfig.allowSystem);
+        assertTrue(mZenModeHelperSpy.mConfig.allowReminders);
+        assertTrue(mZenModeHelperSpy.mConfig.allowCalls);
+        assertTrue(mZenModeHelperSpy.mConfig.allowMessages);
+        assertTrue(mZenModeHelperSpy.mConfig.allowEvents);
+        assertTrue(mZenModeHelperSpy.mConfig.allowRepeatCallers);
+        assertTrue(mZenModeHelperSpy.mConfig.allowWhenScreenOff);
+        assertTrue(mZenModeHelperSpy.mConfig.allowWhenScreenOn);
+        assertEquals(SUPPRESSED_EFFECT_BADGE, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+    }
 }
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index ab106d7..ebdcdfd 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -46,7 +46,8 @@
       message(that.message),
       fields(that.fields),
       primaryFields(that.primaryFields),
-      exclusiveField(that.exclusiveField) {}
+      exclusiveField(that.exclusiveField),
+      uidField(that.uidField) {}
 
 AtomDecl::AtomDecl(int c, const string& n, const string& m)
     :code(c),
@@ -262,6 +263,18 @@
             errorCount++;
         }
     }
+
+    if (field->options().GetExtension(os::statsd::is_uid) == true) {
+        if (javaType != JAVA_TYPE_INT) {
+            errorCount++;
+        }
+
+        if (atomDecl->uidField == 0) {
+            atomDecl->uidField = it->first;
+        } else {
+            errorCount++;
+        }
+    }
   }
 
   return errorCount;
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index edba3e2..5d2c302 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -84,6 +84,8 @@
     vector<int> primaryFields;
     int exclusiveField = 0;
 
+    int uidField = 0;
+
     AtomDecl();
     AtomDecl(const AtomDecl& that);
     AtomDecl(int code, const string& name, const string& message);
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index d58c223..300c701 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -113,6 +113,98 @@
     fprintf(out, "// the single event tag id for all stats logs\n");
     fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
 
+    std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
+                                             "audio_state_changed",
+                                             "call_state_changed",
+                                             "phone_signal_strength_changed",
+                                             "mobile_bytes_transfer_by_fg_bg",
+                                             "mobile_bytes_transfer"};
+    fprintf(out,
+            "const std::set<int> "
+            "AtomsInfo::kNotTruncatingTimestampAtomWhiteList = {\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+         atom != atoms.decls.end(); atom++) {
+        if (kTruncatingAtomNames.find(atom->name) ==
+            kTruncatingAtomNames.end()) {
+            string constant = make_constant_name(atom->name);
+            fprintf(out, " %s,\n", constant.c_str());
+        }
+    }
+    fprintf(out, "};\n");
+    fprintf(out, "\n");
+
+    fprintf(out,
+            "const std::set<int> AtomsInfo::kAtomsWithAttributionChain = {\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+         atom != atoms.decls.end(); atom++) {
+        for (vector<AtomField>::const_iterator field = atom->fields.begin();
+             field != atom->fields.end(); field++) {
+            if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+                string constant = make_constant_name(atom->name);
+                fprintf(out, " %s,\n", constant.c_str());
+                break;
+            }
+        }
+    }
+    fprintf(out, "};\n");
+    fprintf(out, "\n");
+
+    fprintf(out,
+            "static std::map<int, int> "
+            "getAtomUidField() {\n");
+    fprintf(out, "  std::map<int, int> uidField;\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+         atom != atoms.decls.end(); atom++) {
+        if (atom->uidField == 0) {
+            continue;
+        }
+        fprintf(out,
+                "\n    // Adding uid field for atom "
+                "(%d)%s\n",
+                atom->code, atom->name.c_str());
+        fprintf(out, "    uidField[static_cast<int>(%s)] = %d;\n",
+                make_constant_name(atom->name).c_str(), atom->uidField);
+    }
+
+    fprintf(out, "    return uidField;\n");
+    fprintf(out, "};\n");
+
+    fprintf(out,
+            "const std::map<int, int> AtomsInfo::kAtomsWithUidField = "
+            "getAtomUidField();\n");
+
+    fprintf(out,
+            "static std::map<int, StateAtomFieldOptions> "
+            "getStateAtomFieldOptions() {\n");
+    fprintf(out, "    std::map<int, StateAtomFieldOptions> options;\n");
+    fprintf(out, "    StateAtomFieldOptions opt;\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+         atom != atoms.decls.end(); atom++) {
+        if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
+            continue;
+        }
+        fprintf(out,
+                "\n    // Adding primary and exclusive fields for atom "
+                "(%d)%s\n",
+                atom->code, atom->name.c_str());
+        fprintf(out, "    opt.primaryFields.clear();\n");
+        for (const auto& field : atom->primaryFields) {
+            fprintf(out, "    opt.primaryFields.push_back(%d);\n", field);
+        }
+
+        fprintf(out, "    opt.exclusiveField = %d;\n", atom->exclusiveField);
+        fprintf(out, "    options[static_cast<int>(%s)] = opt;\n",
+                make_constant_name(atom->name).c_str());
+    }
+
+    fprintf(out, "    return options;\n");
+    fprintf(out, "  }\n");
+
+    fprintf(out,
+            "const std::map<int, StateAtomFieldOptions> "
+            "AtomsInfo::kStateAtomsFieldOptions = "
+            "getStateAtomFieldOptions();\n");
+
     // Print write methods
     fprintf(out, "\n");
     for (set<vector<java_type_t>>::const_iterator signature = atoms.signatures.begin();
@@ -366,89 +458,26 @@
     fprintf(out, "};\n");
     fprintf(out, "\n");
 
-    std::set<string> kTruncatingAtomNames =
-        { "mobile_radio_power_state_changed", "audio_state_changed", "call_state_changed",
-          "phone_signal_strength_changed", "mobile_bytes_transfer_by_fg_bg",
-          "mobile_bytes_transfer"};
-    fprintf(out, "const static std::set<int> kNotTruncatingTimestampAtomWhiteList = {\n");
-    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
-        atom != atoms.decls.end(); atom++) {
-        if (kTruncatingAtomNames.find(atom->name) == kTruncatingAtomNames.end()) {
-            string constant = make_constant_name(atom->name);
-            fprintf(out, " %s,\n", constant.c_str());
-        }
-    }
-    fprintf(out, "};\n");
-    fprintf(out, "\n");
-
-    fprintf(out, "const static std::set<int> kAtomsWithUidField = {\n");
-    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
-        atom != atoms.decls.end(); atom++) {
-        for (vector<AtomField>::const_iterator field = atom->fields.begin();
-                field != atom->fields.end(); field++) {
-            if (field->name == "uid") {
-                string constant = make_constant_name(atom->name);
-                fprintf(out, " %s,\n", constant.c_str());
-                break;
-            }
-        }
-    }
-    fprintf(out, "};\n");
-    fprintf(out, "\n");
-
-    fprintf(out, "const static std::set<int> kAtomsWithAttributionChain = {\n");
-    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
-        atom != atoms.decls.end(); atom++) {
-        for (vector<AtomField>::const_iterator field = atom->fields.begin();
-                field != atom->fields.end(); field++) {
-            if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                string constant = make_constant_name(atom->name);
-                fprintf(out, " %s,\n", constant.c_str());
-                break;
-            }
-        }
-    }
-    fprintf(out, "};\n");
-    fprintf(out, "\n");
-
-    fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n", maxPushedAtomId);
-
     fprintf(out, "struct StateAtomFieldOptions {\n");
     fprintf(out, "  std::vector<int> primaryFields;\n");
     fprintf(out, "  int exclusiveField;\n");
+    fprintf(out, "};\n");
     fprintf(out, "\n");
+
+    fprintf(out, "struct AtomsInfo {\n");
     fprintf(out,
-            "  static std::map<int, StateAtomFieldOptions> "
-            "getStateAtomFieldOptions() {\n");
-    fprintf(out, "    std::map<int, StateAtomFieldOptions> options;\n");
-    fprintf(out, "    StateAtomFieldOptions opt;\n");
-    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
-         atom != atoms.decls.end(); atom++) {
-        if (atom->primaryFields.size() == 0 && atom->exclusiveField == 0) {
-            continue;
-        }
-        fprintf(out,
-                "\n    // Adding primary and exclusive fields for atom "
-                "(%d)%s\n",
-                atom->code, atom->name.c_str());
-        fprintf(out, "    opt.primaryFields.clear();\n");
-        for (const auto& field : atom->primaryFields) {
-            fprintf(out, "    opt.primaryFields.push_back(%d);\n", field);
-        }
-
-        fprintf(out, "    opt.exclusiveField = %d;\n", atom->exclusiveField);
-        fprintf(out, "    options[static_cast<int>(%s)] = opt;\n",
-                make_constant_name(atom->name).c_str());
-    }
-
-    fprintf(out, "    return options;\n");
-    fprintf(out, "  }\n");
+            "  const static std::set<int> "
+            "kNotTruncatingTimestampAtomWhiteList;\n");
+    fprintf(out, "  const static std::map<int, int> kAtomsWithUidField;\n");
+    fprintf(out,
+            "  const static std::set<int> kAtomsWithAttributionChain;\n");
+    fprintf(out,
+            "  const static std::map<int, StateAtomFieldOptions> "
+            "kStateAtomsFieldOptions;\n");
     fprintf(out, "};\n");
 
-    fprintf(out,
-            "const static std::map<int, StateAtomFieldOptions> "
-            "kStateAtomsFieldOptions = "
-            "StateAtomFieldOptions::getStateAtomFieldOptions();\n");
+    fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
+            maxPushedAtomId);
 
     // Print write methods
     fprintf(out, "//\n");
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 309bc80..2f7b50d 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -28,7 +28,6 @@
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.PasspointManagementObjectDefinition;
 import android.net.wifi.ScanResult;
-import android.net.wifi.ScanSettings;
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
@@ -86,7 +85,7 @@
 
     boolean disableNetwork(int netId, String packageName);
 
-    void startScan(in ScanSettings requested, in WorkSource ws, String packageName);
+    void startScan(String packageName);
 
     List<ScanResult> getScanResults(String callingPackage);
 
diff --git a/wifi/java/android/net/wifi/ScanSettings.aidl b/wifi/java/android/net/wifi/ScanSettings.aidl
deleted file mode 100644
index ebd2a39..0000000
--- a/wifi/java/android/net/wifi/ScanSettings.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2014, 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 android.net.wifi;
-
-parcelable ScanSettings;
diff --git a/wifi/java/android/net/wifi/ScanSettings.java b/wifi/java/android/net/wifi/ScanSettings.java
deleted file mode 100644
index 094ce34..0000000
--- a/wifi/java/android/net/wifi/ScanSettings.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2014, 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 android.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * Bundle of customized scan settings
- *
- * @see WifiManager#startCustomizedScan
- *
- * @hide
- */
-public class ScanSettings implements Parcelable {
-
-    /** channel set to scan. this can be null or empty, indicating a full scan */
-    public Collection<WifiChannel> channelSet;
-
-    /** public constructor */
-    public ScanSettings() { }
-
-    /** copy constructor */
-    public ScanSettings(ScanSettings source) {
-        if (source.channelSet != null)
-            channelSet = new ArrayList<WifiChannel>(source.channelSet);
-    }
-
-    /** check for validity */
-    public boolean isValid() {
-        for (WifiChannel channel : channelSet)
-            if (!channel.isValid()) return false;
-        return true;
-    }
-
-    /** implement Parcelable interface */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** implement Parcelable interface */
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(channelSet == null ? 0 : channelSet.size());
-        if (channelSet != null)
-            for (WifiChannel channel : channelSet) channel.writeToParcel(out, flags);
-    }
-
-    /** implement Parcelable interface */
-    public static final Parcelable.Creator<ScanSettings> CREATOR =
-            new Parcelable.Creator<ScanSettings>() {
-        @Override
-        public ScanSettings createFromParcel(Parcel in) {
-            ScanSettings settings = new ScanSettings();
-            int size = in.readInt();
-            if (size > 0) {
-                settings.channelSet = new ArrayList<WifiChannel>(size);
-                while (size-- > 0)
-                    settings.channelSet.add(WifiChannel.CREATOR.createFromParcel(in));
-            }
-            return settings;
-        }
-
-        @Override
-        public ScanSettings[] newArray(int size) {
-            return new ScanSettings[size];
-        }
-    };
-}
diff --git a/wifi/java/android/net/wifi/WifiChannel.java b/wifi/java/android/net/wifi/WifiChannel.java
deleted file mode 100644
index 640481e..0000000
--- a/wifi/java/android/net/wifi/WifiChannel.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2014, 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 android.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Wifi Channel
- *
- * @see ScanSettings
- *
- * @hide
- */
-public class WifiChannel implements Parcelable {
-
-    private static final int MIN_FREQ_MHZ = 2412;
-    private static final int MAX_FREQ_MHZ = 5825;
-
-    private static final int MIN_CHANNEL_NUM = 1;
-    private static final int MAX_CHANNEL_NUM = 196;
-
-    /** frequency */
-    public int freqMHz;
-
-    /** channel number */
-    public int channelNum;
-
-    /** is it a DFS channel? */
-    public boolean isDFS;
-
-    /** public constructor */
-    public WifiChannel() { }
-
-    /** check for validity */
-    public boolean isValid() {
-        if (freqMHz < MIN_FREQ_MHZ || freqMHz > MAX_FREQ_MHZ) return false;
-        if (channelNum < MIN_CHANNEL_NUM || channelNum > MAX_CHANNEL_NUM) return false;
-        return true;
-    }
-
-    /** implement Parcelable interface */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** implement Parcelable interface */
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(freqMHz);
-        out.writeInt(channelNum);
-        out.writeInt(isDFS ? 1 : 0);
-    }
-
-    /** implement Parcelable interface */
-    public static final Parcelable.Creator<WifiChannel> CREATOR =
-            new Parcelable.Creator<WifiChannel>() {
-        @Override
-        public WifiChannel createFromParcel(Parcel in) {
-            WifiChannel channel = new WifiChannel();
-            channel.freqMHz = in.readInt();
-            channel.channelNum = in.readInt();
-            channel.isDFS = in.readInt() != 0;
-            return channel;
-        }
-
-        @Override
-        public WifiChannel[] newArray(int size) {
-            return new WifiChannel[size];
-        }
-    };
-}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index d2cdf8d..c8df087 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1634,7 +1634,7 @@
     public boolean startScan(WorkSource workSource) {
         try {
             String packageName = mContext.getOpPackageName();
-            mService.startScan(null, workSource, packageName);
+            mService.startScan(packageName);
             return true;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();