Merge "Send installerUid for verification when using PackageInstaller." into mnc-dev
diff --git a/Android.mk b/Android.mk
index e96a932..a02b326 100644
--- a/Android.mk
+++ b/Android.mk
@@ -142,6 +142,7 @@
 	core/java/android/content/pm/IPackageManager.aidl \
 	core/java/android/content/pm/IPackageMoveObserver.aidl \
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
+	core/java/android/content/pm/IPackagesProvider.aidl \
 	core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	core/java/android/hardware/ICameraService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 457a9e8..2058ac9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4016,79 +4016,6 @@
     field public java.lang.String serviceDetails;
   }
 
-  public deprecated class AssistContent {
-    ctor public AssistContent();
-    method public android.content.ClipData getClipData();
-    method public android.os.Bundle getExtras();
-    method public java.lang.String getStructuredData();
-    method public android.net.Uri getWebUri();
-    method public boolean isAppProvidedIntent();
-    method public void setClipData(android.content.ClipData);
-    method public void setIntent(android.content.Intent);
-    method public void setStructuredData(java.lang.String);
-    method public void setWebUri(android.net.Uri);
-  }
-
-  public deprecated class AssistStructure {
-    ctor public AssistStructure();
-    method public android.content.ComponentName getActivityComponent();
-    method public int getWindowNodeCount();
-  }
-
-  public static class AssistStructure.ViewNode {
-    method public android.app.AssistStructure.ViewNode getChildAt(int);
-    method public int getChildCount();
-    method public java.lang.String getClassName();
-    method public java.lang.CharSequence getContentDescription();
-    method public android.os.Bundle getExtras();
-    method public int getHeight();
-    method public java.lang.String getHint();
-    method public int getId();
-    method public java.lang.String getIdEntry();
-    method public java.lang.String getIdPackage();
-    method public java.lang.String getIdType();
-    method public int getLeft();
-    method public int getScrollX();
-    method public int getScrollY();
-    method public java.lang.CharSequence getText();
-    method public int getTextBackgroundColor();
-    method public int getTextColor();
-    method public int getTextSelectionEnd();
-    method public int getTextSelectionStart();
-    method public float getTextSize();
-    method public int getTextStyle();
-    method public int getTop();
-    method public int getVisibility();
-    method public int getWidth();
-    method public boolean isAccessibilityFocused();
-    method public boolean isActivated();
-    method public boolean isAssistBlocked();
-    method public boolean isCheckable();
-    method public boolean isChecked();
-    method public boolean isClickable();
-    method public boolean isContextClickable();
-    method public boolean isEnabled();
-    method public boolean isFocusable();
-    method public boolean isFocused();
-    method public boolean isLongClickable();
-    method public boolean isSelected();
-    field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
-    field public static final int TEXT_STYLE_BOLD = 1; // 0x1
-    field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
-    field public static final int TEXT_STYLE_STRIKE_THRU = 8; // 0x8
-    field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4
-  }
-
-  public static class AssistStructure.WindowNode {
-    method public int getDisplayId();
-    method public int getHeight();
-    method public int getLeft();
-    method public android.app.AssistStructure.ViewNode getRootViewNode();
-    method public java.lang.CharSequence getTitle();
-    method public int getTop();
-    method public int getWidth();
-  }
-
   public class DatePickerDialog extends android.app.AlertDialog implements android.widget.DatePicker.OnDateChangedListener android.content.DialogInterface.OnClickListener {
     ctor public DatePickerDialog(android.content.Context, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
     ctor public DatePickerDialog(android.content.Context, int, android.app.DatePickerDialog.OnDateSetListener, int, int, int);
@@ -5900,22 +5827,87 @@
 
 package android.app.assist {
 
-  public final class AssistContent extends android.app.AssistContent implements android.os.Parcelable {
-    ctor public AssistContent(android.os.Parcel);
+  public deprecated class AssistContent implements android.os.Parcelable {
+    ctor public AssistContent();
     method public int describeContents();
+    method public android.content.ClipData getClipData();
+    method public android.os.Bundle getExtras();
     method public android.content.Intent getIntent();
+    method public java.lang.String getStructuredData();
+    method public android.net.Uri getWebUri();
+    method public boolean isAppProvidedIntent();
+    method public void setClipData(android.content.ClipData);
+    method public void setIntent(android.content.Intent);
+    method public void setStructuredData(java.lang.String);
+    method public void setWebUri(android.net.Uri);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.assist.AssistContent> CREATOR;
   }
 
-  public final class AssistStructure extends android.app.AssistStructure implements android.os.Parcelable {
+  public class AssistStructure implements android.os.Parcelable {
     ctor public AssistStructure();
     method public int describeContents();
-    method public android.app.AssistStructure.WindowNode getWindowNodeAt(int);
+    method public android.content.ComponentName getActivityComponent();
+    method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int);
+    method public int getWindowNodeCount();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR;
   }
 
+  public static class AssistStructure.ViewNode {
+    method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
+    method public int getChildCount();
+    method public java.lang.String getClassName();
+    method public java.lang.CharSequence getContentDescription();
+    method public android.os.Bundle getExtras();
+    method public int getHeight();
+    method public java.lang.String getHint();
+    method public int getId();
+    method public java.lang.String getIdEntry();
+    method public java.lang.String getIdPackage();
+    method public java.lang.String getIdType();
+    method public int getLeft();
+    method public int getScrollX();
+    method public int getScrollY();
+    method public java.lang.CharSequence getText();
+    method public int getTextBackgroundColor();
+    method public int getTextColor();
+    method public int getTextSelectionEnd();
+    method public int getTextSelectionStart();
+    method public float getTextSize();
+    method public int getTextStyle();
+    method public int getTop();
+    method public int getVisibility();
+    method public int getWidth();
+    method public boolean isAccessibilityFocused();
+    method public boolean isActivated();
+    method public boolean isAssistBlocked();
+    method public boolean isCheckable();
+    method public boolean isChecked();
+    method public boolean isClickable();
+    method public boolean isContextClickable();
+    method public boolean isEnabled();
+    method public boolean isFocusable();
+    method public boolean isFocused();
+    method public boolean isLongClickable();
+    method public boolean isSelected();
+    field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
+    field public static final int TEXT_STYLE_BOLD = 1; // 0x1
+    field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
+    field public static final int TEXT_STYLE_STRIKE_THRU = 8; // 0x8
+    field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4
+  }
+
+  public static class AssistStructure.WindowNode {
+    method public int getDisplayId();
+    method public int getHeight();
+    method public int getLeft();
+    method public android.app.assist.AssistStructure.ViewNode getRootViewNode();
+    method public java.lang.CharSequence getTitle();
+    method public int getTop();
+    method public int getWidth();
+  }
+
 }
 
 package android.app.backup {
@@ -7211,6 +7203,7 @@
     method public android.content.Context getContext();
     method public final android.os.IBinder getSyncAdapterBinder();
     method public abstract void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult);
+    method public void onSecurityException(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.SyncResult);
     method public void onSyncCanceled();
     method public void onSyncCanceled(java.lang.Thread);
     field public static final deprecated int LOG_SYNC_DETAILS = 2743; // 0xab7
@@ -13505,7 +13498,6 @@
     field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2
     field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0
     field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1
-    field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3
     field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2
     field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
     field public static final int LENS_FACING_BACK = 1; // 0x1
@@ -13858,6 +13850,7 @@
   }
 
   public final class StreamConfigurationMap {
+    method public android.util.Size[] getHighResolutionOutputSizes(int);
     method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRanges();
     method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size);
     method public android.util.Size[] getHighSpeedVideoSizes();
@@ -18207,7 +18200,6 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
-    method public void onPreCheck(android.net.Network);
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -18358,6 +18350,7 @@
     method public boolean hasTransport(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
+    field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
     field public static final int NET_CAPABILITY_CBS = 5; // 0x5
     field public static final int NET_CAPABILITY_DUN = 2; // 0x2
     field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
@@ -18372,6 +18365,7 @@
     field public static final int NET_CAPABILITY_RCS = 8; // 0x8
     field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
     field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe
+    field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10
     field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
     field public static final int NET_CAPABILITY_XCAP = 9; // 0x9
     field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2
@@ -19085,6 +19079,8 @@
 
   public class ScanResult implements android.os.Parcelable {
     method public int describeContents();
+    method public boolean is80211mcResponder();
+    method public boolean isPasspointNetwork();
     method public void writeToParcel(android.os.Parcel, int);
     field public java.lang.String BSSID;
     field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
@@ -19092,18 +19088,19 @@
     field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
     field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
     field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
+    field public static final long FLAG_80211mc_RESPONDER = 2L; // 0x2L
+    field public static final long FLAG_PASSPOINT_NETWORK = 1L; // 0x1L
     field public java.lang.String SSID;
     field public java.lang.String capabilities;
     field public int centerFreq0;
     field public int centerFreq1;
     field public int channelWidth;
+    field public long flags;
     field public int frequency;
-    field public boolean is80211McRTTResponder;
     field public int level;
-    field public java.lang.String operatorFriendlyName;
-    field public boolean passpointNetwork;
+    field public java.lang.CharSequence operatorFriendlyName;
     field public long timestamp;
-    field public java.lang.String venueName;
+    field public java.lang.CharSequence venueName;
   }
 
   public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -19146,7 +19143,7 @@
     field public java.lang.String preSharedKey;
     field public int priority;
     field public java.lang.String providerFriendlyName;
-    field public java.util.HashSet<java.lang.Long> roamingConsortiumIds;
+    field public java.lang.Long[] roamingConsortiumIds;
     field public int status;
     field public java.lang.String[] wepKeys;
     field public int wepTxKeyIndex;
@@ -19208,7 +19205,7 @@
     method public java.lang.String getAnonymousIdentity();
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate getClientCertificate();
-    method public java.lang.String getDomainSubjectMatch();
+    method public java.lang.String getDomainSuffixMatch();
     method public int getEapMethod();
     method public java.lang.String getIdentity();
     method public java.lang.String getPassword();
@@ -26582,6 +26579,7 @@
     field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
     field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
     field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+    field public static final java.lang.String WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN = "wifi_device_owner_configs_lockdown";
     field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
     field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
     field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
diff --git a/api/system-current.txt b/api/system-current.txt
index 08715cd..df18ce4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4112,79 +4112,6 @@
     field public java.lang.String serviceDetails;
   }
 
-  public deprecated class AssistContent {
-    ctor public AssistContent();
-    method public android.content.ClipData getClipData();
-    method public android.os.Bundle getExtras();
-    method public java.lang.String getStructuredData();
-    method public android.net.Uri getWebUri();
-    method public boolean isAppProvidedIntent();
-    method public void setClipData(android.content.ClipData);
-    method public void setIntent(android.content.Intent);
-    method public void setStructuredData(java.lang.String);
-    method public void setWebUri(android.net.Uri);
-  }
-
-  public deprecated class AssistStructure {
-    ctor public AssistStructure();
-    method public android.content.ComponentName getActivityComponent();
-    method public int getWindowNodeCount();
-  }
-
-  public static class AssistStructure.ViewNode {
-    method public android.app.AssistStructure.ViewNode getChildAt(int);
-    method public int getChildCount();
-    method public java.lang.String getClassName();
-    method public java.lang.CharSequence getContentDescription();
-    method public android.os.Bundle getExtras();
-    method public int getHeight();
-    method public java.lang.String getHint();
-    method public int getId();
-    method public java.lang.String getIdEntry();
-    method public java.lang.String getIdPackage();
-    method public java.lang.String getIdType();
-    method public int getLeft();
-    method public int getScrollX();
-    method public int getScrollY();
-    method public java.lang.CharSequence getText();
-    method public int getTextBackgroundColor();
-    method public int getTextColor();
-    method public int getTextSelectionEnd();
-    method public int getTextSelectionStart();
-    method public float getTextSize();
-    method public int getTextStyle();
-    method public int getTop();
-    method public int getVisibility();
-    method public int getWidth();
-    method public boolean isAccessibilityFocused();
-    method public boolean isActivated();
-    method public boolean isAssistBlocked();
-    method public boolean isCheckable();
-    method public boolean isChecked();
-    method public boolean isClickable();
-    method public boolean isContextClickable();
-    method public boolean isEnabled();
-    method public boolean isFocusable();
-    method public boolean isFocused();
-    method public boolean isLongClickable();
-    method public boolean isSelected();
-    field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
-    field public static final int TEXT_STYLE_BOLD = 1; // 0x1
-    field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
-    field public static final int TEXT_STYLE_STRIKE_THRU = 8; // 0x8
-    field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4
-  }
-
-  public static class AssistStructure.WindowNode {
-    method public int getDisplayId();
-    method public int getHeight();
-    method public int getLeft();
-    method public android.app.AssistStructure.ViewNode getRootViewNode();
-    method public java.lang.CharSequence getTitle();
-    method public int getTop();
-    method public int getWidth();
-  }
-
   public class BroadcastOptions {
     method public static android.app.BroadcastOptions makeBasic();
     method public void setTemporaryAppWhitelistDuration(long);
@@ -6018,22 +5945,87 @@
 
 package android.app.assist {
 
-  public final class AssistContent extends android.app.AssistContent implements android.os.Parcelable {
-    ctor public AssistContent(android.os.Parcel);
+  public deprecated class AssistContent implements android.os.Parcelable {
+    ctor public AssistContent();
     method public int describeContents();
+    method public android.content.ClipData getClipData();
+    method public android.os.Bundle getExtras();
     method public android.content.Intent getIntent();
+    method public java.lang.String getStructuredData();
+    method public android.net.Uri getWebUri();
+    method public boolean isAppProvidedIntent();
+    method public void setClipData(android.content.ClipData);
+    method public void setIntent(android.content.Intent);
+    method public void setStructuredData(java.lang.String);
+    method public void setWebUri(android.net.Uri);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.assist.AssistContent> CREATOR;
   }
 
-  public final class AssistStructure extends android.app.AssistStructure implements android.os.Parcelable {
+  public class AssistStructure implements android.os.Parcelable {
     ctor public AssistStructure();
     method public int describeContents();
-    method public android.app.AssistStructure.WindowNode getWindowNodeAt(int);
+    method public android.content.ComponentName getActivityComponent();
+    method public android.app.assist.AssistStructure.WindowNode getWindowNodeAt(int);
+    method public int getWindowNodeCount();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.assist.AssistStructure> CREATOR;
   }
 
+  public static class AssistStructure.ViewNode {
+    method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
+    method public int getChildCount();
+    method public java.lang.String getClassName();
+    method public java.lang.CharSequence getContentDescription();
+    method public android.os.Bundle getExtras();
+    method public int getHeight();
+    method public java.lang.String getHint();
+    method public int getId();
+    method public java.lang.String getIdEntry();
+    method public java.lang.String getIdPackage();
+    method public java.lang.String getIdType();
+    method public int getLeft();
+    method public int getScrollX();
+    method public int getScrollY();
+    method public java.lang.CharSequence getText();
+    method public int getTextBackgroundColor();
+    method public int getTextColor();
+    method public int getTextSelectionEnd();
+    method public int getTextSelectionStart();
+    method public float getTextSize();
+    method public int getTextStyle();
+    method public int getTop();
+    method public int getVisibility();
+    method public int getWidth();
+    method public boolean isAccessibilityFocused();
+    method public boolean isActivated();
+    method public boolean isAssistBlocked();
+    method public boolean isCheckable();
+    method public boolean isChecked();
+    method public boolean isClickable();
+    method public boolean isContextClickable();
+    method public boolean isEnabled();
+    method public boolean isFocusable();
+    method public boolean isFocused();
+    method public boolean isLongClickable();
+    method public boolean isSelected();
+    field public static final int TEXT_COLOR_UNDEFINED = 1; // 0x1
+    field public static final int TEXT_STYLE_BOLD = 1; // 0x1
+    field public static final int TEXT_STYLE_ITALIC = 2; // 0x2
+    field public static final int TEXT_STYLE_STRIKE_THRU = 8; // 0x8
+    field public static final int TEXT_STYLE_UNDERLINE = 4; // 0x4
+  }
+
+  public static class AssistStructure.WindowNode {
+    method public int getDisplayId();
+    method public int getHeight();
+    method public int getLeft();
+    method public android.app.assist.AssistStructure.ViewNode getRootViewNode();
+    method public java.lang.CharSequence getTitle();
+    method public int getTop();
+    method public int getWidth();
+  }
+
 }
 
 package android.app.backup {
@@ -7436,6 +7428,7 @@
     method public android.content.Context getContext();
     method public final android.os.IBinder getSyncAdapterBinder();
     method public abstract void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult);
+    method public void onSecurityException(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.SyncResult);
     method public void onSyncCanceled();
     method public void onSyncCanceled(java.lang.Thread);
     field public static final deprecated int LOG_SYNC_DETAILS = 2743; // 0xab7
@@ -13836,7 +13829,6 @@
     field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2
     field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0
     field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1
-    field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3
     field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2
     field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
     field public static final int LENS_FACING_BACK = 1; // 0x1
@@ -14189,6 +14181,7 @@
   }
 
   public final class StreamConfigurationMap {
+    method public android.util.Size[] getHighResolutionOutputSizes(int);
     method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRanges();
     method public android.util.Range<java.lang.Integer>[] getHighSpeedVideoFpsRangesFor(android.util.Size);
     method public android.util.Size[] getHighSpeedVideoSizes();
@@ -19708,7 +19701,6 @@
     method public void onLinkPropertiesChanged(android.net.Network, android.net.LinkProperties);
     method public void onLosing(android.net.Network, int);
     method public void onLost(android.net.Network);
-    method public void onPreCheck(android.net.Network);
   }
 
   public static abstract interface ConnectivityManager.OnNetworkActiveListener {
@@ -19859,6 +19851,7 @@
     method public boolean hasTransport(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
+    field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11
     field public static final int NET_CAPABILITY_CBS = 5; // 0x5
     field public static final int NET_CAPABILITY_DUN = 2; // 0x2
     field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
@@ -19873,6 +19866,7 @@
     field public static final int NET_CAPABILITY_RCS = 8; // 0x8
     field public static final int NET_CAPABILITY_SUPL = 1; // 0x1
     field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe
+    field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10
     field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6
     field public static final int NET_CAPABILITY_XCAP = 9; // 0x9
     field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2
@@ -20827,6 +20821,8 @@
 
   public class ScanResult implements android.os.Parcelable {
     method public int describeContents();
+    method public boolean is80211mcResponder();
+    method public boolean isPasspointNetwork();
     method public void writeToParcel(android.os.Parcel, int);
     field public java.lang.String BSSID;
     field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
@@ -20834,18 +20830,19 @@
     field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
     field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
     field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
+    field public static final long FLAG_80211mc_RESPONDER = 2L; // 0x2L
+    field public static final long FLAG_PASSPOINT_NETWORK = 1L; // 0x1L
     field public java.lang.String SSID;
     field public java.lang.String capabilities;
     field public int centerFreq0;
     field public int centerFreq1;
     field public int channelWidth;
+    field public long flags;
     field public int frequency;
-    field public boolean is80211McRTTResponder;
     field public int level;
-    field public java.lang.String operatorFriendlyName;
-    field public boolean passpointNetwork;
+    field public java.lang.CharSequence operatorFriendlyName;
     field public long timestamp;
-    field public java.lang.String venueName;
+    field public java.lang.CharSequence venueName;
   }
 
   public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -20895,7 +20892,7 @@
     field public java.lang.String preSharedKey;
     field public int priority;
     field public java.lang.String providerFriendlyName;
-    field public java.util.HashSet<java.lang.Long> roamingConsortiumIds;
+    field public java.lang.Long[] roamingConsortiumIds;
     field public int status;
     field public java.lang.String[] wepKeys;
     field public int wepTxKeyIndex;
@@ -20972,7 +20969,7 @@
     method public java.lang.String getAnonymousIdentity();
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate getClientCertificate();
-    method public java.lang.String getDomainSubjectMatch();
+    method public java.lang.String getDomainSuffixMatch();
     method public int getEapMethod();
     method public java.lang.String getIdentity();
     method public java.lang.String getPassword();
@@ -28630,6 +28627,7 @@
     field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
     field public static final java.lang.String USE_GOOGLE_MAIL = "use_google_mail";
     field public static final java.lang.String WAIT_FOR_DEBUGGER = "wait_for_debugger";
+    field public static final java.lang.String WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN = "wifi_device_owner_configs_lockdown";
     field public static final java.lang.String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
     field public static final java.lang.String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
     field public static final java.lang.String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
diff --git a/cmds/hid/Android.mk b/cmds/hid/Android.mk
new file mode 100644
index 0000000..ff3691d
--- /dev/null
+++ b/cmds/hid/Android.mk
@@ -0,0 +1,18 @@
+# Copyright 2015 The Android Open Source Project
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := hid
+LOCAL_JNI_SHARED_LIBRARIES := libhidcommand_jni
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := hid
+LOCAL_SRC_FILES := hid
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := EXECUTABLES
+include $(BUILD_PREBUILT)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/cmds/hid/MODULE_LICENSE_APACHE2 b/cmds/hid/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/hid/MODULE_LICENSE_APACHE2
diff --git a/cmds/hid/NOTICE b/cmds/hid/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/hid/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/cmds/hid/hid b/cmds/hid/hid
new file mode 100755
index 0000000..2359fcd
--- /dev/null
+++ b/cmds/hid/hid
@@ -0,0 +1,8 @@
+#!/system/bin/sh
+#
+# Script to start "hid" on the device, which has a very rudimentary
+# shell.
+#
+base=/system
+export CLASSPATH=$base/framework/hid.jar
+exec app_process $base/bin com.android.commands.hid.Hid "$@"
diff --git a/cmds/hid/jni/Android.mk b/cmds/hid/jni/Android.mk
new file mode 100644
index 0000000..8163a9d
--- /dev/null
+++ b/cmds/hid/jni/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    com_android_commands_hid_Device.cpp
+
+LOCAL_C_INCLUDES := \
+    $(JNI_H_INCLUDE) \
+    frameworks/base/core/jni
+
+LOCAL_SHARED_LIBRARIES := \
+    libandroid_runtime \
+    liblog \
+    libnativehelper \
+    libutils
+
+LOCAL_MODULE := libhidcommand_jni
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS += -Wall
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
new file mode 100644
index 0000000..4278e7d
--- /dev/null
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "HidCommandDevice"
+
+#include "com_android_commands_hid_Device.h"
+
+#include <linux/uhid.h>
+
+#include <fcntl.h>
+#include <cstdio>
+#include <cstring>
+#include <memory>
+#include <unistd.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <android_os_MessageQueue.h>
+#include <core_jni_helpers.h>
+#include <jni.h>
+#include <JNIHelp.h>
+#include <ScopedPrimitiveArray.h>
+#include <ScopedUtfChars.h>
+#include <utils/Log.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace uhid {
+
+static const char* UHID_PATH = "/dev/uhid";
+static const size_t UHID_MAX_NAME_LENGTH = 128;
+
+static struct {
+    jmethodID onDeviceOpen;
+    jmethodID onDeviceError;
+} gDeviceCallbackClassInfo;
+
+static int handleLooperEvents(int fd, int events, void* data) {
+    Device* d = reinterpret_cast<Device*>(data);
+    return d->handleEvents(events);
+}
+
+static void checkAndClearException(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        ALOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+    }
+}
+
+DeviceCallback::DeviceCallback(JNIEnv* env, jobject callback) :
+    mCallbackObject(env->NewGlobalRef(callback)) { }
+
+DeviceCallback::~DeviceCallback() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteGlobalRef(mCallbackObject);
+}
+
+void DeviceCallback::onDeviceError() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceError);
+    checkAndClearException(env, "onDeviceError");
+}
+
+void DeviceCallback::onDeviceOpen() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOpen);
+    checkAndClearException(env, "onDeviceOpen");
+}
+
+Device* Device::open(int32_t id, const char* name, int32_t vid, int32_t pid,
+        std::unique_ptr<uint8_t[]> descriptor, size_t descriptorSize,
+        std::unique_ptr<DeviceCallback> callback, sp<Looper> looper) {
+
+    int fd = ::open(UHID_PATH, O_RDWR | O_CLOEXEC);
+    if (fd < 0) {
+        ALOGE("Failed to open uhid: %s", strerror(errno));
+        return nullptr;
+    }
+
+    struct uhid_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.type = UHID_CREATE;
+    strncpy((char*)ev.u.create.name, name, UHID_MAX_NAME_LENGTH);
+    ev.u.create.rd_data = descriptor.get();
+    ev.u.create.rd_size = descriptorSize;
+    ev.u.create.bus = BUS_BLUETOOTH;
+    ev.u.create.vendor = vid;
+    ev.u.create.product = pid;
+    ev.u.create.version = 0;
+    ev.u.create.country = 0;
+
+    errno = 0;
+    ssize_t ret = TEMP_FAILURE_RETRY(::write(fd, &ev, sizeof(ev)));
+    if (ret < 0 || ret != sizeof(ev)) {
+        ::close(fd);
+        ALOGE("Failed to create uhid node: %s", strerror(errno));
+        return nullptr;
+    }
+
+    // Wait for the device to actually be created.
+    ret = TEMP_FAILURE_RETRY(::read(fd, &ev, sizeof(ev)));
+    if (ret < 0 || ev.type != UHID_START) {
+        ::close(fd);
+        ALOGE("uhid node failed to start: %s", strerror(errno));
+        return nullptr;
+    }
+
+    return new Device(id, fd, std::move(callback), looper);
+}
+
+Device::Device(int32_t id, int fd, std::unique_ptr<DeviceCallback> callback, sp<Looper> looper) :
+            mId(id), mFd(fd), mDeviceCallback(std::move(callback)), mLooper(looper) {
+    looper->addFd(fd, 0, Looper::EVENT_INPUT, handleLooperEvents, reinterpret_cast<void*>(this));
+}
+
+Device::~Device() {
+    mLooper->removeFd(mFd);
+    struct uhid_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.type = UHID_DESTROY;
+    TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
+    ::close(mFd);
+    mFd = -1;
+}
+
+void Device::sendReport(uint8_t* report, size_t reportSize) {
+    struct uhid_event ev;
+    memset(&ev, 0, sizeof(ev));
+    ev.type = UHID_INPUT;
+    ev.u.input.size = reportSize;
+    memcpy(&ev.u.input.data, report, reportSize);
+    ssize_t ret = TEMP_FAILURE_RETRY(::write(mFd, &ev, sizeof(ev)));
+    if (ret < 0 || ret != sizeof(ev)) {
+        ALOGE("Failed to send hid event: %s", strerror(errno));
+    }
+}
+
+int Device::handleEvents(int events) {
+    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+        ALOGE("uhid node was closed or an error occurred. events=0x%x", events);
+        mDeviceCallback->onDeviceError();
+        return 0;
+    }
+    struct uhid_event ev;
+    ssize_t ret = TEMP_FAILURE_RETRY(::read(mFd, &ev, sizeof(ev)));
+    if (ret < 0) {
+        ALOGE("Failed to read from uhid node: %s", strerror(errno));
+        mDeviceCallback->onDeviceError();
+        return 0;
+    }
+
+    if (ev.type == UHID_OPEN) {
+        mDeviceCallback->onDeviceOpen();
+    }
+
+    return 1;
+}
+
+} // namespace uhid
+
+std::unique_ptr<uint8_t[]> getData(JNIEnv* env, jbyteArray javaArray, size_t& outSize) {
+    ScopedByteArrayRO scopedArray(env, javaArray);
+    outSize = scopedArray.size();
+    std::unique_ptr<uint8_t[]> data(new uint8_t[outSize]);
+    for (size_t i = 0; i < outSize; i++) {
+        data[i] = static_cast<uint8_t>(scopedArray[i]);
+    }
+    return data;
+}
+
+static jlong openDevice(JNIEnv* env, jclass clazz, jstring rawName, jint id, jint vid, jint pid,
+        jbyteArray rawDescriptor, jobject queue, jobject callback) {
+    ScopedUtfChars name(env, rawName);
+    if (name.c_str() == nullptr) {
+        return 0;
+    }
+
+    size_t size;
+    std::unique_ptr<uint8_t[]> desc = getData(env, rawDescriptor, size);
+
+    std::unique_ptr<uhid::DeviceCallback> cb(new uhid::DeviceCallback(env, callback));
+    sp<Looper> looper = android_os_MessageQueue_getMessageQueue(env, queue)->getLooper();
+
+    uhid::Device* d = uhid::Device::open(
+            id, reinterpret_cast<const char*>(name.c_str()), vid, pid,
+            std::move(desc), size, std::move(cb), std::move(looper));
+    return reinterpret_cast<jlong>(d);
+}
+
+static void sendReport(JNIEnv* env, jclass clazz, jlong ptr,jbyteArray rawReport) {
+    size_t size;
+    std::unique_ptr<uint8_t[]> report = getData(env, rawReport, size);
+    uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
+    if (d) {
+        d->sendReport(report.get(), size);
+    }
+}
+
+static void closeDevice(JNIEnv* env, jclass clazz, jlong ptr) {
+    uhid::Device* d = reinterpret_cast<uhid::Device*>(ptr);
+    if (d) {
+        delete d;
+    }
+}
+
+static JNINativeMethod sMethods[] = {
+    { "nativeOpenDevice",
+            "(Ljava/lang/String;III[BLandroid/os/MessageQueue;"
+            "Lcom/android/commands/hid/Device$DeviceCallback;)J",
+            reinterpret_cast<void*>(openDevice) },
+    { "nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport) },
+    { "nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice) },
+};
+
+int register_com_android_commands_hid_Device(JNIEnv* env) {
+    jclass clazz = FindClassOrDie(env, "com/android/commands/hid/Device$DeviceCallback");
+    uhid::gDeviceCallbackClassInfo.onDeviceOpen =
+            GetMethodIDOrDie(env, clazz, "onDeviceOpen", "()V");
+    uhid::gDeviceCallbackClassInfo.onDeviceError=
+            GetMethodIDOrDie(env, clazz, "onDeviceError", "()V");
+    return jniRegisterNativeMethods(env, "com/android/commands/hid/Device",
+            sMethods, NELEM(sMethods));
+}
+
+} // namespace android
+
+jint JNI_OnLoad(JavaVM* jvm, void*) {
+    JNIEnv *env = NULL;
+    if (jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) {
+        return JNI_ERR;
+    }
+
+    if (android::register_com_android_commands_hid_Device(env) < 0 ){
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_6;
+}
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
new file mode 100644
index 0000000..6c5899e
--- /dev/null
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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 <memory>
+
+#include <jni.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace uhid {
+
+class DeviceCallback {
+public:
+    DeviceCallback(JNIEnv* env, jobject callback);
+    ~DeviceCallback();
+
+    void onDeviceOpen();
+    void onDeviceError();
+
+private:
+    jobject mCallbackObject;
+};
+
+class Device {
+public:
+    static Device* open(int32_t id, const char* name, int32_t vid, int32_t pid,
+            std::unique_ptr<uint8_t[]> descriptor, size_t descriptorSize,
+            std::unique_ptr<DeviceCallback> callback, sp<Looper> looper);
+
+    Device(int32_t id, int fd, std::unique_ptr<DeviceCallback> callback, sp<Looper> looper);
+    ~Device();
+
+    void sendReport(uint8_t* report, size_t reportSize);
+    void close();
+
+    int handleEvents(int events);
+
+private:
+    int32_t mId;
+    int mFd;
+    std::unique_ptr<DeviceCallback> mDeviceCallback;
+    sp<Looper> mLooper;
+};
+
+
+} // namespace uhid
+} // namespace android
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
new file mode 100644
index 0000000..dbe883b
--- /dev/null
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.hid;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.internal.os.SomeArgs;
+
+public class Device {
+    private static final String TAG = "HidDevice";
+
+    // Minimum amount of time to wait before sending input events to a device. Even though we're
+    // guaranteed that the device has been created and opened by the input system, there's still a
+    // window in which the system hasn't started reading events out of it. If a stream of events
+    // begins in during this window (like a button down event) and *then* we start reading, we're
+    // liable to ignore the whole stream.
+    private static final int MIN_WAIT_FOR_FIRST_EVENT = 150;
+
+    private static final int MSG_OPEN_DEVICE = 1;
+    private static final int MSG_SEND_REPORT = 2;
+    private static final int MSG_CLOSE_DEVICE = 3;
+
+
+    private final int mId;
+    private final HandlerThread mThread;
+    private final DeviceHandler mHandler;
+    private long mEventTime;
+
+    private final Object mCond = new Object();
+
+    static {
+        System.loadLibrary("hidcommand_jni");
+    }
+
+    private static native long nativeOpenDevice(String name, int id, int vid, int pid,
+            byte[] descriptor, MessageQueue queue, DeviceCallback callback);
+    private static native void nativeSendReport(long ptr, byte[] data);
+    private static native void nativeCloseDevice(long ptr);
+
+    public Device(int id, String name, int vid, int pid, byte[] descriptor, byte[] report) {
+        mId = id;
+        mThread = new HandlerThread("HidDeviceHandler");
+        mThread.start();
+        mHandler = new DeviceHandler(mThread.getLooper());
+        SomeArgs args = SomeArgs.obtain();
+        args.argi1 = id;
+        args.argi2 = vid;
+        args.argi3 = pid;
+        if (name != null) {
+            args.arg1 = name;
+        } else {
+            args.arg1 = id + ":" + vid + ":" + pid;
+        }
+        args.arg2 = descriptor;
+        args.arg3 = report;
+        mHandler.obtainMessage(MSG_OPEN_DEVICE, args).sendToTarget();
+        mEventTime = SystemClock.uptimeMillis() + MIN_WAIT_FOR_FIRST_EVENT;
+    }
+
+    public void sendReport(byte[] report) {
+        Message msg = mHandler.obtainMessage(MSG_SEND_REPORT, report);
+        mHandler.sendMessageAtTime(msg, mEventTime);
+    }
+
+    public void addDelay(int delay) {
+        mEventTime += delay;
+    }
+
+    public void close() {
+        Message msg = mHandler.obtainMessage(MSG_CLOSE_DEVICE);
+        msg.setAsynchronous(true);
+        mHandler.sendMessageAtTime(msg, mEventTime + 1);
+        try {
+            synchronized (mCond) {
+                mCond.wait();
+            }
+        } catch (InterruptedException ignore) {}
+    }
+
+    private class DeviceHandler extends Handler {
+        private long mPtr;
+        private int mBarrierToken;
+
+        public DeviceHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_OPEN_DEVICE:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    mPtr = nativeOpenDevice((String) args.arg1, args.argi1, args.argi2, args.argi3,
+                            (byte[]) args.arg2, getLooper().myQueue(), new DeviceCallback());
+                    nativeSendReport(mPtr, (byte[]) args.arg3);
+                    pauseEvents();
+                    break;
+                case MSG_SEND_REPORT:
+                    if (mPtr != 0) {
+                        nativeSendReport(mPtr, (byte[]) msg.obj);
+                    } else {
+                        Log.e(TAG, "Tried to send report to closed device.");
+                    }
+                    break;
+                case MSG_CLOSE_DEVICE:
+                    if (mPtr != 0) {
+                        nativeCloseDevice(mPtr);
+                        getLooper().quitSafely();
+                        mPtr = 0;
+                    } else {
+                        Log.e(TAG, "Tried to close already closed device.");
+                    }
+                    synchronized (mCond) {
+                        mCond.notify();
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown device message");
+            }
+        }
+
+        public void pauseEvents() {
+            mBarrierToken = getLooper().myQueue().postSyncBarrier();
+        }
+
+        public void resumeEvents() {
+            getLooper().myQueue().removeSyncBarrier(mBarrierToken);
+            mBarrierToken = 0;
+        }
+    }
+
+    private class DeviceCallback {
+        public void onDeviceOpen() {
+            mHandler.resumeEvents();
+        }
+
+        public void onDeviceError() {
+            Message msg = mHandler.obtainMessage(MSG_CLOSE_DEVICE);
+            msg.setAsynchronous(true);
+            msg.sendToTarget();
+        }
+    }
+}
diff --git a/cmds/hid/src/com/android/commands/hid/Event.java b/cmds/hid/src/com/android/commands/hid/Event.java
new file mode 100644
index 0000000..c6a37bd
--- /dev/null
+++ b/cmds/hid/src/com/android/commands/hid/Event.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.hid;
+
+import android.util.JsonReader;
+import android.util.JsonToken;
+import android.util.Log;
+
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Event {
+    private static final String TAG = "HidEvent";
+
+    public static final String COMMAND_REGISTER = "register";
+    public static final String COMMAND_DELAY = "delay";
+    public static final String COMMAND_REPORT = "report";
+
+    private int mId;
+    private String mCommand;
+    private String mName;
+    private byte[] mDescriptor;
+    private int mVid;
+    private int mPid;
+    private byte[] mReport;
+    private int mDuration;
+
+    public int getId() {
+        return mId;
+    }
+
+    public String getCommand() {
+        return mCommand;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public byte[] getDescriptor() {
+        return mDescriptor;
+    }
+
+    public int getVendorId() {
+        return mVid;
+    }
+
+    public int getProductId() {
+        return mPid;
+    }
+
+    public byte[] getReport() {
+        return mReport;
+    }
+
+    public int getDuration() {
+        return mDuration;
+    }
+
+    public String toString() {
+        return "Event{id=" + mId
+            + ", command=" + String.valueOf(mCommand)
+            + ", name=" + String.valueOf(mName)
+            + ", descriptor=" + Arrays.toString(mDescriptor)
+            + ", vid=" + mVid
+            + ", pid=" + mPid
+            + ", report=" + Arrays.toString(mReport)
+            + ", duration=" + mDuration
+            + "}";
+    }
+
+    private static class Builder {
+        private Event mEvent;
+
+        public Builder() {
+            mEvent = new Event();
+        }
+
+        public void setId(int id) {
+            mEvent.mId = id;
+        }
+
+        private void setCommand(String command) {
+            mEvent.mCommand = command;
+        }
+
+        public void setName(String name) {
+            mEvent.mName = name;
+        }
+
+        public void setDescriptor(byte[] descriptor) {
+            mEvent.mDescriptor = descriptor;
+        }
+
+        public void setReport(byte[] report) {
+            mEvent.mReport = report;
+        }
+
+        public void setVid(int vid) {
+            mEvent.mVid = vid;
+        }
+
+        public void setPid(int pid) {
+            mEvent.mPid = pid;
+        }
+
+        public void setDuration(int duration) {
+            mEvent.mDuration = duration;
+        }
+
+        public Event build() {
+            if (mEvent.mId == -1) {
+                throw new IllegalStateException("No event id");
+            } else if (mEvent.mCommand == null) {
+                throw new IllegalStateException("Event does not contain a command");
+            }
+            if (COMMAND_REGISTER.equals(mEvent.mCommand)) {
+                if (mEvent.mDescriptor == null) {
+                    throw new IllegalStateException("Device registration is missing descriptor");
+                }
+            } else if (COMMAND_DELAY.equals(mEvent.mCommand)) {
+                if (mEvent.mDuration <= 0) {
+                    throw new IllegalStateException("Delay has missing or invalid duration");
+                }
+            } else if (COMMAND_REPORT.equals(mEvent.mCommand)) {
+                if (mEvent.mReport == null) {
+                    throw new IllegalStateException("Report command is missing report data");
+                }
+            }
+            return mEvent;
+        }
+    }
+
+    public static class Reader {
+        private JsonReader mReader;
+
+        public Reader(InputStreamReader in) {
+            mReader = new JsonReader(in);
+            mReader.setLenient(true);
+        }
+
+        public Event getNextEvent() throws IOException {
+            Event e = null;
+            while (e == null && mReader.peek() != JsonToken.END_DOCUMENT) {
+                Event.Builder eb = new Event.Builder();
+                try {
+                    mReader.beginObject();
+                    while (mReader.hasNext()) {
+                        String name = mReader.nextName();
+                        switch (name) {
+                            case "id":
+                                eb.setId(readInt());
+                                break;
+                            case "command":
+                                eb.setCommand(mReader.nextString());
+                                break;
+                            case "descriptor":
+                                eb.setDescriptor(readData());
+                                break;
+                            case "name":
+                                eb.setName(mReader.nextString());
+                                break;
+                            case "vid":
+                                eb.setVid(readInt());
+                                break;
+                            case "pid":
+                                eb.setPid(readInt());
+                                break;
+                            case "report":
+                                eb.setReport(readData());
+                                break;
+                            case "duration":
+                                eb.setDuration(readInt());
+                                break;
+                            default:
+                                mReader.skipValue();
+                        }
+                    }
+                    mReader.endObject();
+                } catch (IllegalStateException ex) {
+                    error("Error reading in object, ignoring.", ex);
+                    consumeRemainingElements();
+                    mReader.endObject();
+                    continue;
+                }
+                e = eb.build();
+            }
+
+            return e;
+        }
+
+        private byte[] readData() throws IOException {
+            ArrayList<Integer> data = new ArrayList<Integer>();
+            try {
+                mReader.beginArray();
+                while (mReader.hasNext()) {
+                    data.add(Integer.decode(mReader.nextString()));
+                }
+                mReader.endArray();
+            } catch (IllegalStateException|NumberFormatException e) {
+                consumeRemainingElements();
+                mReader.endArray();
+                throw new IllegalStateException("Encountered malformed data.", e);
+            }
+            byte[] rawData = new byte[data.size()];
+            for (int i = 0; i < data.size(); i++) {
+                int d = data.get(i);
+                if ((d & 0xFF) != d) {
+                    throw new IllegalStateException("Invalid data, all values must be byte-sized");
+                }
+                rawData[i] = (byte)d;
+            }
+            return rawData;
+        }
+
+        private int readInt() throws IOException {
+            String val = mReader.nextString();
+            return Integer.decode(val);
+        }
+
+        private void consumeRemainingElements() throws IOException {
+            while (mReader.hasNext()) {
+                mReader.skipValue();
+            }
+        }
+    }
+
+    private static void error(String msg) {
+        error(msg, null);
+    }
+
+    private static void error(String msg, Exception e) {
+        System.out.println(msg);
+        Log.e(TAG, msg);
+        if (e != null) {
+            Log.e(TAG, Log.getStackTraceString(e));
+        }
+    }
+}
diff --git a/cmds/hid/src/com/android/commands/hid/Hid.java b/cmds/hid/src/com/android/commands/hid/Hid.java
new file mode 100644
index 0000000..976a782
--- /dev/null
+++ b/cmds/hid/src/com/android/commands/hid/Hid.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.hid;
+
+import android.os.SystemClock;
+import android.util.JsonReader;
+import android.util.JsonToken;
+import android.util.Log;
+import android.util.SparseArray;
+
+import libcore.io.IoUtils;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+public class Hid {
+    private static final String TAG = "HID";
+
+    private final Event.Reader mReader;
+    private final SparseArray<Device> mDevices;
+
+    private static void usage() {
+        error("Usage: hid [FILE]");
+    }
+
+    public static void main(String[] args) {
+        if (args.length != 1) {
+            usage();
+            System.exit(1);
+        }
+
+        InputStream stream = null;
+        try {
+            if (args[0].equals("-")) {
+                stream = System.in;
+            } else {
+                File f = new File(args[0]);
+                stream = new FileInputStream(f);
+            }
+            (new Hid(stream)).run();
+        } catch (Exception e) {
+            error("HID injection failed.", e);
+            System.exit(1);
+        } finally {
+            IoUtils.closeQuietly(stream);
+        }
+    }
+
+    private Hid(InputStream in) {
+        mDevices = new SparseArray<Device>();
+        try {
+            mReader = new Event.Reader(new InputStreamReader(in, "UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void run() {
+        try {
+            Event e = null;
+            while ((e = mReader.getNextEvent()) != null) {
+                process(e);
+            }
+        } catch (IOException ex) {
+            error("Error reading in events.", ex);
+        }
+
+        for (int i = 0; i < mDevices.size(); i++) {
+            mDevices.valueAt(i).close();
+        }
+    }
+
+
+    private void process(Event e) {
+        final int index = mDevices.indexOfKey(e.getId());
+        if (index >= 0) {
+            Device d = mDevices.valueAt(index);
+            if (Event.COMMAND_DELAY.equals(e.getCommand())) {
+                d.addDelay(e.getDuration());
+            } else if (Event.COMMAND_REPORT.equals(e.getCommand())) {
+                d.sendReport(e.getReport());
+            } else {
+                error("Unknown command \"" + e.getCommand() + "\". Ignoring event.");
+            }
+        } else {
+            registerDevice(e);
+        }
+    }
+
+    private void registerDevice(Event e) {
+        if (!Event.COMMAND_REGISTER.equals(e.getCommand())) {
+            throw new IllegalStateException(
+                    "Tried to send command \"" + e.getCommand() + "\" to an unregistered device!");
+        }
+        int id = e.getId();
+        Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(),
+                e.getDescriptor(), e.getReport());
+        mDevices.append(id, d);
+    }
+
+    private static void error(String msg) {
+        error(msg, null);
+    }
+
+    private static void error(String msg, Exception e) {
+        System.out.println(msg);
+        Log.e(TAG, msg);
+        if (e != null) {
+            Log.e(TAG, Log.getStackTraceString(e));
+        }
+    }
+}
diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java
index 64f023f..fb050e5 100644
--- a/cmds/wm/src/com/android/commands/wm/Wm.java
+++ b/cmds/wm/src/com/android/commands/wm/Wm.java
@@ -54,6 +54,7 @@
                 "       wm density [reset|DENSITY]\n" +
                 "       wm overscan [reset|LEFT,TOP,RIGHT,BOTTOM]\n" +
                 "       wm scaling [off|auto]\n" +
+                "       wm screen-capture [userId] [true|false]\n" +
                 "\n" +
                 "wm size: return or override display size.\n" +
                 "         width and height in pixels unless suffixed with 'dp'.\n" +
@@ -62,7 +63,9 @@
                 "\n" +
                 "wm overscan: set overscan area for display.\n" +
                 "\n" +
-                "wm scaling: set display scaling mode.\n"
+                "wm scaling: set display scaling mode.\n" +
+                "\n" +
+                "wm screen-capture: enable/disable screen capture.\n"
                 );
     }
 
@@ -85,16 +88,39 @@
             runDisplayOverscan();
         } else if (op.equals("scaling")) {
             runDisplayScaling();
+        } else if (op.equals("screen-capture")) {
+            runSetScreenCapture();
         } else {
             showError("Error: unknown command '" + op + "'");
             return;
         }
     }
 
+    private void runSetScreenCapture() throws Exception {
+        String userIdStr = nextArg();
+        String enableStr = nextArg();
+        int userId;
+        boolean disable;
+
+        try {
+            userId = Integer.parseInt(userIdStr);
+        } catch (NumberFormatException e) {
+            System.err.println("Error: bad number " + e);
+            return;
+        }
+
+        disable = !Boolean.parseBoolean(enableStr);
+
+        try {
+            mWm.setScreenCaptureDisabled(userId, disable);
+        } catch (RemoteException e) {
+            System.err.println("Error: Can't set screen capture " + e);
+        }
+    }
+
     private void runDisplaySize() throws Exception {
         String size = nextArg();
         int w, h;
-        boolean scale = true;
         if (size == null) {
             Point initialSize = new Point();
             Point baseSize = new Point();
@@ -181,7 +207,6 @@
     private void runDisplayOverscan() throws Exception {
         String overscanStr = nextArgRequired();
         Rect rect = new Rect();
-        int density;
         if ("reset".equals(overscanStr)) {
             rect.set(0, 0, 0, 0);
         } else {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 1b4ee2e..e8ab109 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2075,6 +2075,9 @@
                     "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " +
                     "android:windowActionBar to false in your theme to use a Toolbar instead.");
         }
+        // Clear out the MenuInflater to make sure that it is valid for the new Action Bar
+        mMenuInflater = null;
+
         ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this);
         mActionBar = tbab;
         mWindow.setCallback(tbab.getWrappedWindowCallback());
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
deleted file mode 100644
index ad2ba39..0000000
--- a/core/java/android/app/AssistContent.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2015 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;
-
-import android.content.ClipData;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Holds information about the content an application is viewing, to hand to an
- * assistant at the user's request.  This is filled in by
- * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
- * @deprecated use {@link android.app.assist.AssistContent}.
- */
-@Deprecated
-public class AssistContent {
-    private boolean mIsAppProvidedIntent = false;
-    private Intent mIntent;
-    private String mStructuredData;
-    private ClipData mClipData;
-    private Uri mUri;
-    private final Bundle mExtras;
-
-    /**
-     * @hide
-     * Key name this data structure is stored in the Bundle generated by
-     * {@link android.app.Activity#onProvideAssistData}.
-     */
-    public static final String ASSIST_KEY = "android:assist_content";
-
-    /**
-     * @hide
-     * Retrieve the framework-generated AssistContent that is stored within
-     * the Bundle filled in by {@link android.app.Activity#onProvideAssistContent}.
-     */
-    public static android.app.assist.AssistContent getAssistContent(Bundle assistBundle) {
-        return assistBundle.getParcelable(ASSIST_KEY);
-    }
-
-    public AssistContent() {
-        mExtras = new Bundle();
-    }
-
-    /**
-     * @hide
-     * Called by {@link android.app.ActivityThread} to set the default Intent based on
-     * {@link android.app.Activity#getIntent Activity.getIntent}.
-     *
-     * <p>Automatically populates {@link #mUri} if that Intent is an {@link Intent#ACTION_VIEW}
-     * of a web (http or https scheme) URI.</p>
-     */
-    public void setDefaultIntent(Intent intent) {
-        mIntent = intent;
-        setWebUri(null);
-        if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
-            Uri uri = intent.getData();
-            if (uri != null) {
-                if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) {
-                    setWebUri(uri);
-                }
-            }
-        }
-    }
-
-    /**
-     * Sets the Intent associated with the content, describing the current top-level context of
-     * the activity.  If this contains a reference to a piece of data related to the activity,
-     * be sure to set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} so the accessibility
-     * service can access it.
-     */
-    public void setIntent(Intent intent) {
-        mIsAppProvidedIntent = true;
-        mIntent = intent;
-    }
-
-    /**
-     * Returns the current {@link #setIntent} if one is set, else the default Intent obtained from
-     * {@link android.app.Activity#getIntent Activity.getIntent}. Can be modified in-place.
-     * @hide
-     */
-    public Intent getIntent() {
-        return mIntent;
-    }
-
-    /**
-     * Returns whether or not the current Intent was explicitly provided in
-     * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not,
-     * the Intent was automatically set based on
-     * {@link android.app.Activity#getIntent Activity.getIntent}.
-     */
-    public boolean isAppProvidedIntent() {
-        return mIsAppProvidedIntent;
-    }
-
-    /**
-     * Optional additional content items that are involved with
-     * the current UI.  Access to this content will be granted to the assistant as if you
-     * are sending it through an Intent with {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
-     */
-    public void setClipData(ClipData clip) {
-        mClipData = clip;
-    }
-
-    /**
-     * Return the current {@link #setClipData}, which you can modify in-place.
-     */
-    public ClipData getClipData() {
-        return mClipData;
-    }
-
-    /**
-     * Sets optional structured data regarding the content being viewed. The provided data
-     * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the
-     * <a href="http://schema.org/">schema.org</a> vocabulary.
-     */
-    public void setStructuredData(String structuredData) {
-        mStructuredData = structuredData;
-    }
-
-    /**
-     * Returns the current {@link #setStructuredData}.
-     */
-    public String getStructuredData() {
-        return mStructuredData;
-    }
-
-    /**
-     * Set a web URI associated with the current data being shown to the user.
-     * This URI could be opened in a web browser, or in the app as an
-     * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently
-     * being displayed by it.  The URI here should be something that is transportable
-     * off the device into other environments to acesss the same data as is currently
-     * being shown in the app; if the app does not have such a representation, it should
-     * leave the null and only report the local intent and clip data.
-     */
-    public void setWebUri(Uri uri) {
-        mUri = uri;
-    }
-
-    /**
-     * Return the content's web URI as per {@link #setWebUri(android.net.Uri)}, or null if
-     * there is none.
-     */
-    public Uri getWebUri() {
-        return mUri;
-    }
-
-    /**
-     * Return Bundle for extra vendor-specific data that can be modified and examined.
-     */
-    public Bundle getExtras() {
-        return mExtras;
-    }
-
-    /** @hide */
-    public AssistContent(Parcel in) {
-        if (in.readInt() != 0) {
-            mIntent = Intent.CREATOR.createFromParcel(in);
-        }
-        if (in.readInt() != 0) {
-            mClipData = ClipData.CREATOR.createFromParcel(in);
-        }
-        if (in.readInt() != 0) {
-            mUri = Uri.CREATOR.createFromParcel(in);
-        }
-        if (in.readInt() != 0) {
-            mStructuredData = in.readString();
-        }
-        mIsAppProvidedIntent = in.readInt() == 1;
-        mExtras = in.readBundle();
-    }
-
-    /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
-        if (mIntent != null) {
-            dest.writeInt(1);
-            mIntent.writeToParcel(dest, flags);
-        } else {
-            dest.writeInt(0);
-        }
-        if (mClipData != null) {
-            dest.writeInt(1);
-            mClipData.writeToParcel(dest, flags);
-        } else {
-            dest.writeInt(0);
-        }
-        if (mUri != null) {
-            dest.writeInt(1);
-            mUri.writeToParcel(dest, flags);
-        } else {
-            dest.writeInt(0);
-        }
-        if (mStructuredData != null) {
-            dest.writeInt(1);
-            dest.writeString(mStructuredData);
-        } else {
-            dest.writeInt(0);
-        }
-        dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
-        dest.writeBundle(mExtras);
-    }
-}
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
deleted file mode 100644
index 7f6dae5..0000000
--- a/core/java/android/app/AssistStructure.java
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- * Copyright (C) 2015 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;
-
-import android.content.ComponentName;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.PooledStringReader;
-import android.os.PooledStringWriter;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewAssistStructure;
-import android.view.ViewRootImpl;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-
-import java.util.ArrayList;
-
-/**
- * Assist data automatically created by the platform's implementation
- * of {@link android.app.Activity#onProvideAssistData}.
- * @deprecated use {@link android.app.assist.AssistStructure}.
- */
-@Deprecated
-public class AssistStructure {
-    static final String TAG = "AssistStructure";
-
-    /**
-     * @hide
-     * Key name this data structure is stored in the Bundle generated by
-     * {@link android.app.Activity#onProvideAssistData}.
-     */
-    public static final String ASSIST_KEY = "android:assist_structure";
-
-    /** @hide */
-    public boolean mHaveData;
-
-    ComponentName mActivityComponent;
-
-    final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
-
-    final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
-
-    /** @hide */
-    public SendChannel mSendChannel;
-    /** @hide */
-    public IBinder mReceiveChannel;
-
-    Rect mTmpRect = new Rect();
-
-    static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
-    static final String DESCRIPTOR = "android.app.AssistStructure";
-
-    /** @hide */
-    public final class SendChannel extends Binder {
-        @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                throws RemoteException {
-            if (code == TRANSACTION_XFER) {
-                data.enforceInterface(DESCRIPTOR);
-                writeContentToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-                return true;
-            } else {
-                return super.onTransact(code, data, reply, flags);
-            }
-        }
-    }
-
-    final static class ViewNodeText {
-        CharSequence mText;
-        int mTextSelectionStart;
-        int mTextSelectionEnd;
-        int mTextColor;
-        int mTextBackgroundColor;
-        float mTextSize;
-        int mTextStyle;
-        String mHint;
-
-        ViewNodeText() {
-        }
-
-        ViewNodeText(Parcel in) {
-            mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            mTextSelectionStart = in.readInt();
-            mTextSelectionEnd = in.readInt();
-            mTextColor = in.readInt();
-            mTextBackgroundColor = in.readInt();
-            mTextSize = in.readFloat();
-            mTextStyle = in.readInt();
-            mHint = in.readString();
-        }
-
-        void writeToParcel(Parcel out) {
-            TextUtils.writeToParcel(mText, out, 0);
-            out.writeInt(mTextSelectionStart);
-            out.writeInt(mTextSelectionEnd);
-            out.writeInt(mTextColor);
-            out.writeInt(mTextBackgroundColor);
-            out.writeFloat(mTextSize);
-            out.writeInt(mTextStyle);
-            out.writeString(mHint);
-        }
-    }
-
-    /**
-     * Describes a window in the assist data.
-     */
-    static public class WindowNode {
-        final int mX;
-        final int mY;
-        final int mWidth;
-        final int mHeight;
-        final CharSequence mTitle;
-        final int mDisplayId;
-        final ViewNode mRoot;
-
-        WindowNode(AssistStructure assist, ViewRootImpl root) {
-            View view = root.getView();
-            Rect rect = new Rect();
-            view.getBoundsOnScreen(rect);
-            mX = rect.left - view.getLeft();
-            mY = rect.top - view.getTop();
-            mWidth = rect.width();
-            mHeight = rect.height();
-            mTitle = root.getTitle();
-            mDisplayId = root.getDisplayId();
-            mRoot = new ViewNode();
-            ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
-            if ((root.getWindowFlags()&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
-                // This is a secure window, so it doesn't want a screenshot, and that
-                // means we should also not copy out its view hierarchy.
-                view.onProvideStructure(builder);
-                builder.setAssistBlocked(true);
-                return;
-            }
-            view.dispatchProvideStructure(builder);
-        }
-
-        WindowNode(Parcel in, PooledStringReader preader) {
-            mX = in.readInt();
-            mY = in.readInt();
-            mWidth = in.readInt();
-            mHeight = in.readInt();
-            mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            mDisplayId = in.readInt();
-            mRoot = new ViewNode(in, preader);
-        }
-
-        void writeToParcel(Parcel out, PooledStringWriter pwriter) {
-            out.writeInt(mX);
-            out.writeInt(mY);
-            out.writeInt(mWidth);
-            out.writeInt(mHeight);
-            TextUtils.writeToParcel(mTitle, out, 0);
-            out.writeInt(mDisplayId);
-            mRoot.writeToParcel(out, pwriter);
-        }
-
-        /**
-         * Returns the left edge of the window, in pixels, relative to the left
-         * edge of the screen.
-         */
-        public int getLeft() {
-            return mX;
-        }
-
-        /**
-         * Returns the top edge of the window, in pixels, relative to the top
-         * edge of the screen.
-         */
-        public int getTop() {
-            return mY;
-        }
-
-        /**
-         * Returns the total width of the window in pixels.
-         */
-        public int getWidth() {
-            return mWidth;
-        }
-
-        /**
-         * Returns the total height of the window in pixels.
-         */
-        public int getHeight() {
-            return mHeight;
-        }
-
-        /**
-         * Returns the title associated with the window, if it has one.
-         */
-        public CharSequence getTitle() {
-            return mTitle;
-        }
-
-        /**
-         * Returns the ID of the display this window is on, for use with
-         * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}.
-         */
-        public int getDisplayId() {
-            return mDisplayId;
-        }
-
-        /**
-         * Returns the {@link ViewNode} containing the root content of the window.
-         */
-        public ViewNode getRootViewNode() {
-            return mRoot;
-        }
-    }
-
-    /**
-     * Describes a single view in the assist data.
-     */
-    static public class ViewNode {
-        /**
-         * Magic value for text color that has not been defined, which is very unlikely
-         * to be confused with a real text color.
-         */
-        public static final int TEXT_COLOR_UNDEFINED = 1;
-
-        public static final int TEXT_STYLE_BOLD = 1<<0;
-        public static final int TEXT_STYLE_ITALIC = 1<<1;
-        public static final int TEXT_STYLE_UNDERLINE = 1<<2;
-        public static final int TEXT_STYLE_STRIKE_THRU = 1<<3;
-
-        int mId;
-        String mIdPackage;
-        String mIdType;
-        String mIdEntry;
-        int mX;
-        int mY;
-        int mScrollX;
-        int mScrollY;
-        int mWidth;
-        int mHeight;
-
-        static final int FLAGS_DISABLED = 0x00000001;
-        static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
-        static final int FLAGS_FOCUSABLE = 0x00000010;
-        static final int FLAGS_FOCUSED = 0x00000020;
-        static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000;
-        static final int FLAGS_SELECTED = 0x00000040;
-        static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
-        static final int FLAGS_ACTIVATED = 0x40000000;
-        static final int FLAGS_CHECKABLE = 0x00000100;
-        static final int FLAGS_CHECKED = 0x00000200;
-        static final int FLAGS_CLICKABLE = 0x00004000;
-        static final int FLAGS_LONG_CLICKABLE = 0x00200000;
-        static final int FLAGS_CONTEXT_CLICKABLE = 0x00400000;
-
-        int mFlags;
-
-        String mClassName;
-        CharSequence mContentDescription;
-
-        ViewNodeText mText;
-        Bundle mExtras;
-
-        ViewNode[] mChildren;
-
-        ViewNode() {
-        }
-
-        ViewNode(Parcel in, PooledStringReader preader) {
-            mId = in.readInt();
-            if (mId != 0) {
-                mIdEntry = preader.readString();
-                if (mIdEntry != null) {
-                    mIdType = preader.readString();
-                    mIdPackage = preader.readString();
-                } else {
-                    mIdPackage = mIdType = null;
-                }
-            } else {
-                mIdPackage = mIdType = mIdEntry = null;
-            }
-            mX = in.readInt();
-            mY = in.readInt();
-            mScrollX = in.readInt();
-            mScrollY = in.readInt();
-            mWidth = in.readInt();
-            mHeight = in.readInt();
-            mFlags = in.readInt();
-            mClassName = preader.readString();
-            mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            if (in.readInt() != 0) {
-                mText = new ViewNodeText(in);
-            } else {
-                mText = null;
-            }
-            mExtras = in.readBundle();
-            final int NCHILDREN = in.readInt();
-            if (NCHILDREN > 0) {
-                mChildren = new ViewNode[NCHILDREN];
-                for (int i=0; i<NCHILDREN; i++) {
-                    mChildren[i] = new ViewNode(in, preader);
-                }
-            } else {
-                mChildren = null;
-            }
-        }
-
-        void writeToParcel(Parcel out, PooledStringWriter pwriter) {
-            out.writeInt(mId);
-            if (mId != 0) {
-                pwriter.writeString(mIdEntry);
-                if (mIdEntry != null) {
-                    pwriter.writeString(mIdType);
-                    pwriter.writeString(mIdPackage);
-                }
-            }
-            out.writeInt(mX);
-            out.writeInt(mY);
-            out.writeInt(mScrollX);
-            out.writeInt(mScrollY);
-            out.writeInt(mWidth);
-            out.writeInt(mHeight);
-            out.writeInt(mFlags);
-            pwriter.writeString(mClassName);
-            TextUtils.writeToParcel(mContentDescription, out, 0);
-            if (mText != null) {
-                out.writeInt(1);
-                mText.writeToParcel(out);
-            } else {
-                out.writeInt(0);
-            }
-            out.writeBundle(mExtras);
-            if (mChildren != null) {
-                final int NCHILDREN = mChildren.length;
-                out.writeInt(NCHILDREN);
-                for (int i=0; i<NCHILDREN; i++) {
-                    mChildren[i].writeToParcel(out, pwriter);
-                }
-            } else {
-                out.writeInt(0);
-            }
-        }
-
-        /**
-         * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
-         */
-        public int getId() {
-            return mId;
-        }
-
-        /**
-         * If {@link #getId()} is a resource identifier, this is the package name of that
-         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
-         * for more information.
-         */
-        public String getIdPackage() {
-            return mIdPackage;
-        }
-
-        /**
-         * If {@link #getId()} is a resource identifier, this is the type name of that
-         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
-         * for more information.
-         */
-        public String getIdType() {
-            return mIdType;
-        }
-
-        /**
-         * If {@link #getId()} is a resource identifier, this is the entry name of that
-         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
-         * for more information.
-         */
-        public String getIdEntry() {
-            return mIdEntry;
-        }
-
-        /**
-         * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
-         */
-        public int getLeft() {
-            return mX;
-        }
-
-        /**
-         * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
-         */
-        public int getTop() {
-            return mY;
-        }
-
-        /**
-         * Returns the current X scroll offset of this view, as per
-         * {@link android.view.View#getScrollX() View.getScrollX()}.
-         */
-        public int getScrollX() {
-            return mScrollX;
-        }
-
-        /**
-         * Returns the current Y scroll offset of this view, as per
-         * {@link android.view.View#getScrollX() View.getScrollY()}.
-         */
-        public int getScrollY() {
-            return mScrollY;
-        }
-
-        /**
-         * Returns the width of this view, in pixels.
-         */
-        public int getWidth() {
-            return mWidth;
-        }
-
-        /**
-         * Returns the height of this view, in pixels.
-         */
-        public int getHeight() {
-            return mHeight;
-        }
-
-        /**
-         * Returns the visibility mode of this view, as per
-         * {@link android.view.View#getVisibility() View.getVisibility()}.
-         */
-        public int getVisibility() {
-            return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
-        }
-
-        /**
-         * Returns true if assist data has been blocked starting at this node in the hierarchy.
-         */
-        public boolean isAssistBlocked() {
-            return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0;
-        }
-
-        /**
-         * Returns true if this node is in an enabled state.
-         */
-        public boolean isEnabled() {
-            return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
-        }
-
-        /**
-         * Returns true if this node is clickable by the user.
-         */
-        public boolean isClickable() {
-            return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
-        }
-
-        /**
-         * Returns true if this node can take input focus.
-         */
-        public boolean isFocusable() {
-            return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
-        }
-
-        /**
-         * Returns true if this node currently had input focus at the time that the
-         * structure was collected.
-         */
-        public boolean isFocused() {
-            return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
-        }
-
-        /**
-         * Returns true if this node currently had accessibility focus at the time that the
-         * structure was collected.
-         */
-        public boolean isAccessibilityFocused() {
-            return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
-        }
-
-        /**
-         * Returns true if this node represents something that is checkable by the user.
-         */
-        public boolean isCheckable() {
-            return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
-        }
-
-        /**
-         * Returns true if this node is currently in a checked state.
-         */
-        public boolean isChecked() {
-            return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
-        }
-
-        /**
-         * Returns true if this node has currently been selected by the user.
-         */
-        public boolean isSelected() {
-            return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
-        }
-
-        /**
-         * Returns true if this node has currently been activated by the user.
-         */
-        public boolean isActivated() {
-            return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
-        }
-
-        /**
-         * Returns true if this node is something the user can perform a long click/press on.
-         */
-        public boolean isLongClickable() {
-            return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
-        }
-
-        /**
-         * Returns true if this node is something the user can perform a context click on.
-         */
-        public boolean isContextClickable() {
-            return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
-        }
-
-        /**
-         * Returns the class name of the node's implementation, indicating its behavior.
-         * For example, a button will report "android.widget.Button" meaning it behaves
-         * like a {@link android.widget.Button}.
-         */
-        public String getClassName() {
-            return mClassName;
-        }
-
-        /**
-         * Returns any content description associated with the node, which semantically describes
-         * its purpose for accessibility and other uses.
-         */
-        public CharSequence getContentDescription() {
-            return mContentDescription;
-        }
-
-        /**
-         * Returns any text associated with the node that is displayed to the user, or null
-         * if there is none.
-         */
-        public CharSequence getText() {
-            return mText != null ? mText.mText : null;
-        }
-
-        /**
-         * If {@link #getText()} is non-null, this is where the current selection starts.
-         */
-        public int getTextSelectionStart() {
-            return mText != null ? mText.mTextSelectionStart : -1;
-        }
-
-        /**
-         * If {@link #getText()} is non-null, this is where the current selection starts.
-         * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
-         * indicating the cursor position.
-         */
-        public int getTextSelectionEnd() {
-            return mText != null ? mText.mTextSelectionEnd : -1;
-        }
-
-        /**
-         * If {@link #getText()} is non-null, this is the main text color associated with it.
-         * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
-         * Note that the text may also contain style spans that modify the color of specific
-         * parts of the text.
-         */
-        public int getTextColor() {
-            return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
-        }
-
-        /**
-         * If {@link #getText()} is non-null, this is the main text background color associated
-         * with it.
-         * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
-         * Note that the text may also contain style spans that modify the color of specific
-         * parts of the text.
-         */
-        public int getTextBackgroundColor() {
-            return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
-        }
-
-        /**
-         * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
-         * with it.
-         * Note that the text may also contain style spans that modify the size of specific
-         * parts of the text.
-         */
-        public float getTextSize() {
-            return mText != null ? mText.mTextSize : 0;
-        }
-
-        /**
-         * If {@link #getText()} is non-null, this is the main text style associated
-         * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
-         * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
-         * {@link #TEXT_STYLE_UNDERLINE}.
-         * Note that the text may also contain style spans that modify the style of specific
-         * parts of the text.
-         */
-        public int getTextStyle() {
-            return mText != null ? mText.mTextStyle : 0;
-        }
-
-        /**
-         * Return additional hint text associated with the node; this is typically used with
-         * a node that takes user input, describing to the user what the input means.
-         */
-        public String getHint() {
-            return mText != null ? mText.mHint : null;
-        }
-
-        /**
-         * Return a Bundle containing optional vendor-specific extension information.
-         */
-        public Bundle getExtras() {
-            return mExtras;
-        }
-
-        /**
-         * Return the number of children this node has.
-         */
-        public int getChildCount() {
-            return mChildren != null ? mChildren.length : 0;
-        }
-
-        /**
-         * Return a child of this node, given an index value from 0 to
-         * {@link #getChildCount()}-1.
-         */
-        public ViewNode getChildAt(int index) {
-            return mChildren[index];
-        }
-    }
-
-    static class ViewNodeBuilder extends ViewAssistStructure {
-        final AssistStructure mAssist;
-        final ViewNode mNode;
-        final boolean mAsync;
-
-        ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
-            mAssist = assist;
-            mNode = node;
-            mAsync = async;
-        }
-
-        @Override
-        public void setId(int id, String packageName, String typeName, String entryName) {
-            mNode.mId = id;
-            mNode.mIdPackage = packageName;
-            mNode.mIdType = typeName;
-            mNode.mIdEntry = entryName;
-        }
-
-        @Override
-        public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
-            mNode.mX = left;
-            mNode.mY = top;
-            mNode.mScrollX = scrollX;
-            mNode.mScrollY = scrollY;
-            mNode.mWidth = width;
-            mNode.mHeight = height;
-        }
-
-        @Override
-        public void setVisibility(int visibility) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_VISIBILITY_MASK) | visibility;
-        }
-
-        @Override
-        public void setAssistBlocked(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
-                    | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED);
-        }
-
-        @Override
-        public void setEnabled(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
-                    | (state ? 0 : ViewNode.FLAGS_DISABLED);
-        }
-
-        @Override
-        public void setClickable(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE)
-                    | (state ? ViewNode.FLAGS_CLICKABLE : 0);
-        }
-
-        @Override
-        public void setLongClickable(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE)
-                    | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0);
-        }
-
-        @Override
-        public void setContextClickable(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE)
-                    | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0);
-        }
-
-        @Override
-        public void setFocusable(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
-                    | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
-        }
-
-        @Override
-        public void setFocused(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED)
-                    | (state ? ViewNode.FLAGS_FOCUSED : 0);
-        }
-
-        @Override
-        public void setAccessibilityFocused(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED)
-                    | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0);
-        }
-
-        @Override
-        public void setCheckable(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE)
-                    | (state ? ViewNode.FLAGS_CHECKABLE : 0);
-        }
-
-        @Override
-        public void setChecked(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED)
-                    | (state ? ViewNode.FLAGS_CHECKED : 0);
-        }
-
-        @Override
-        public void setSelected(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED)
-                    | (state ? ViewNode.FLAGS_SELECTED : 0);
-        }
-
-        @Override
-        public void setActivated(boolean state) {
-            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED)
-                    | (state ? ViewNode.FLAGS_ACTIVATED : 0);
-        }
-
-        @Override
-        public void setClassName(String className) {
-            mNode.mClassName = className;
-        }
-
-        @Override
-        public void setContentDescription(CharSequence contentDescription) {
-            mNode.mContentDescription = contentDescription;
-        }
-
-        private final ViewNodeText getNodeText() {
-            if (mNode.mText != null) {
-                return mNode.mText;
-            }
-            mNode.mText = new ViewNodeText();
-            return mNode.mText;
-        }
-
-        @Override
-        public void setText(CharSequence text) {
-            ViewNodeText t = getNodeText();
-            t.mText = text;
-            t.mTextSelectionStart = t.mTextSelectionEnd = -1;
-        }
-
-        @Override
-        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
-            ViewNodeText t = getNodeText();
-            t.mText = text;
-            t.mTextSelectionStart = selectionStart;
-            t.mTextSelectionEnd = selectionEnd;
-        }
-
-        @Override
-        public void setTextStyle(float size, int fgColor, int bgColor, int style) {
-            ViewNodeText t = getNodeText();
-            t.mTextColor = fgColor;
-            t.mTextBackgroundColor = bgColor;
-            t.mTextSize = size;
-            t.mTextStyle = style;
-        }
-
-        @Override
-        public void setHint(CharSequence hint) {
-            getNodeText().mHint = hint != null ? hint.toString() : null;
-        }
-
-        @Override
-        public CharSequence getText() {
-            return mNode.mText != null ? mNode.mText.mText : null;
-        }
-
-        @Override
-        public int getTextSelectionStart() {
-            return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1;
-        }
-
-        @Override
-        public int getTextSelectionEnd() {
-            return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1;
-        }
-
-        @Override
-        public CharSequence getHint() {
-            return mNode.mText != null ? mNode.mText.mHint : null;
-        }
-
-        @Override
-        public Bundle getExtras() {
-            if (mNode.mExtras != null) {
-                return mNode.mExtras;
-            }
-            mNode.mExtras = new Bundle();
-            return mNode.mExtras;
-        }
-
-        @Override
-        public boolean hasExtras() {
-            return mNode.mExtras != null;
-        }
-
-        @Override
-        public void setChildCount(int num) {
-            mNode.mChildren = new ViewNode[num];
-        }
-
-        @Override
-        public int addChildCount(int num) {
-            if (mNode.mChildren == null) {
-                setChildCount(num);
-                return 0;
-            }
-            final int start = mNode.mChildren.length;
-            ViewNode[] newArray = new ViewNode[start + num];
-            System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
-            mNode.mChildren = newArray;
-            return start;
-        }
-
-        @Override
-        public int getChildCount() {
-            return mNode.mChildren != null ? mNode.mChildren.length : 0;
-        }
-
-        @Override
-        public ViewAssistStructure newChild(int index) {
-            ViewNode node = new ViewNode();
-            mNode.mChildren[index] = node;
-            return new ViewNodeBuilder(mAssist, node, false);
-        }
-
-        @Override
-        public ViewAssistStructure asyncNewChild(int index) {
-            synchronized (mAssist) {
-                ViewNode node = new ViewNode();
-                mNode.mChildren[index] = node;
-                ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
-                mAssist.mPendingAsyncChildren.add(builder);
-                return builder;
-            }
-        }
-
-        @Override
-        public void asyncCommit() {
-            synchronized (mAssist) {
-                if (!mAsync) {
-                    throw new IllegalStateException("Child " + this
-                            + " was not created with ViewAssistStructure.asyncNewChild");
-                }
-                if (!mAssist.mPendingAsyncChildren.remove(this)) {
-                    throw new IllegalStateException("Child " + this + " already committed");
-                }
-                mAssist.notifyAll();
-            }
-        }
-
-        @Override
-        public Rect getTempRect() {
-            return mAssist.mTmpRect;
-        }
-    }
-
-    /** @hide */
-    public AssistStructure(Activity activity) {
-        mHaveData = true;
-        mActivityComponent = activity.getComponentName();
-        ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
-                activity.getActivityToken());
-        for (int i=0; i<views.size(); i++) {
-            ViewRootImpl root = views.get(i);
-            mWindowNodes.add(new WindowNode(this, root));
-        }
-    }
-
-    public AssistStructure() {
-        mHaveData = true;
-        mActivityComponent = null;
-    }
-
-    /** @hide */
-    public AssistStructure(Parcel in) {
-        mReceiveChannel = in.readStrongBinder();
-    }
-
-    /** @hide */
-    public void dump() {
-        Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString());
-        final int N = getWindowNodeCount();
-        for (int i=0; i<N; i++) {
-            WindowNode node = getWindowNodeAt(i);
-            Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop()
-                    + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle());
-            dump("  ", node.getRootViewNode());
-        }
-    }
-
-    void dump(String prefix, ViewNode node) {
-        Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop()
-                + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName());
-        int id = node.getId();
-        if (id != 0) {
-            StringBuilder sb = new StringBuilder();
-            sb.append(prefix); sb.append("  ID: #"); sb.append(Integer.toHexString(id));
-            String entry = node.getIdEntry();
-            if (entry != null) {
-                String type = node.getIdType();
-                String pkg = node.getIdPackage();
-                sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type);
-                sb.append("/"); sb.append(entry);
-            }
-            Log.i(TAG, sb.toString());
-        }
-        int scrollX = node.getScrollX();
-        int scrollY = node.getScrollY();
-        if (scrollX != 0 || scrollY != 0) {
-            Log.i(TAG, prefix + "  Scroll: " + scrollX + "," + scrollY);
-        }
-        CharSequence contentDescription = node.getContentDescription();
-        if (contentDescription != null) {
-            Log.i(TAG, prefix + "  Content description: " + contentDescription);
-        }
-        CharSequence text = node.getText();
-        if (text != null) {
-            Log.i(TAG, prefix + "  Text (sel " + node.getTextSelectionStart() + "-"
-                    + node.getTextSelectionEnd() + "): " + text);
-            Log.i(TAG, prefix + "  Text size: " + node.getTextSize() + " , style: #"
-                    + node.getTextStyle());
-            Log.i(TAG, prefix + "  Text color fg: #" + Integer.toHexString(node.getTextColor())
-                    + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
-        }
-        String hint = node.getHint();
-        if (hint != null) {
-            Log.i(TAG, prefix + "  Hint: " + hint);
-        }
-        Bundle extras = node.getExtras();
-        if (extras != null) {
-            Log.i(TAG, prefix + "  Extras: " + extras);
-        }
-        final int NCHILDREN = node.getChildCount();
-        if (NCHILDREN > 0) {
-            Log.i(TAG, prefix + "  Children:");
-            String cprefix = prefix + "    ";
-            for (int i=0; i<NCHILDREN; i++) {
-                ViewNode cnode = node.getChildAt(i);
-                dump(cprefix, cnode);
-            }
-        }
-    }
-
-    /**
-     * @hide
-     * Retrieve the framework-generated AssistStructure that is stored within
-     * the Bundle filled in by {@link Activity#onProvideAssistData}.
-     */
-    public static android.app.assist.AssistStructure getAssistStructure(Bundle assistBundle) {
-        return assistBundle.getParcelable(ASSIST_KEY);
-    }
-
-    /**
-     * Return the activity this AssistStructure came from.
-     */
-    public ComponentName getActivityComponent() {
-        ensureData();
-        return mActivityComponent;
-    }
-
-    /**
-     * Return the number of window contents that have been collected in this assist data.
-     */
-    public int getWindowNodeCount() {
-        ensureData();
-        return mWindowNodes.size();
-    }
-
-    /**
-     * Return one of the windows in the assist data.
-     * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
-     * @hide
-     */
-    public WindowNode getWindowNodeAt(int index) {
-        ensureData();
-        return mWindowNodes.get(index);
-    }
-
-    /** @hide */
-    public void ensureData() {
-        if (mHaveData) {
-            return;
-        }
-        mHaveData = true;
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(DESCRIPTOR);
-        try {
-            mReceiveChannel.transact(TRANSACTION_XFER, data, reply, 0);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failure reading AssistStructure data", e);
-            return;
-        }
-        readContentFromParcel(reply);
-        data.recycle();
-        reply.recycle();
-    }
-
-    void writeContentToParcel(Parcel out, int flags) {
-        // First make sure all content has been created.
-        boolean skipStructure = false;
-        synchronized (this) {
-            long endTime = SystemClock.uptimeMillis() + 5000;
-            long now;
-            while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) {
-                try {
-                    wait(endTime-now);
-                } catch (InterruptedException e) {
-                }
-            }
-            if (mPendingAsyncChildren.size() > 0) {
-                // We waited too long, assume none of the assist structure is valid.
-                skipStructure = true;
-            }
-        }
-        int start = out.dataPosition();
-        PooledStringWriter pwriter = new PooledStringWriter(out);
-        ComponentName.writeToParcel(mActivityComponent, out);
-        final int N = skipStructure ? 0 : mWindowNodes.size();
-        out.writeInt(N);
-        for (int i=0; i<N; i++) {
-            mWindowNodes.get(i).writeToParcel(out, pwriter);
-        }
-        pwriter.finish();
-        Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes");
-    }
-
-    void readContentFromParcel(Parcel in) {
-        PooledStringReader preader = new PooledStringReader(in);
-        mActivityComponent = ComponentName.readFromParcel(in);
-        final int N = in.readInt();
-        for (int i=0; i<N; i++) {
-            mWindowNodes.add(new WindowNode(in, preader));
-        }
-        //dump();
-    }
-}
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 9cc399d..abb8244 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -225,6 +225,9 @@
          * Cancel this active request.
          */
         public void cancel() {
+            if (mRequestInterface == null) {
+                throw new IllegalStateException("Request " + this + " is no longer active");
+            }
             try {
                 mRequestInterface.cancel();
             } catch (RemoteException e) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 125708a..4d1cff5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3972,6 +3972,7 @@
      * <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN}
      * This setting is only available from {@link android.os.Build.VERSION_CODES#MNC} onwards
      * and can only be set if {@link #setMaximumTimeToLock} is not used to set a timeout.</li>
+     * <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li>
      * </ul>
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -4349,6 +4350,12 @@
      * group that the runtime permission belongs to. This method can only be called
      * by a profile or device owner.
      *
+     * <p/>Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not
+     * revoke the permission. It retains the previous grant, if any.
+     *
+     * <p/>Permissions can be granted or revoked only for applications built with a
+     * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#MNC} or later.
+     *
      * @param admin Which profile or device owner this request is associated with.
      * @param packageName The application to grant or revoke a permission to.
      * @param permission The permission to grant or revoke.
diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java
index c7e7330..07b2d57 100644
--- a/core/java/android/app/assist/AssistContent.java
+++ b/core/java/android/app/assist/AssistContent.java
@@ -1,24 +1,184 @@
 package android.app.assist;
 
+import android.content.ClipData;
 import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
- * New home for AssistContent.
+ * Holds information about the content an application is viewing, to hand to an
+ * assistant at the user's request.  This is filled in by
+ * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
  */
-public final class AssistContent extends android.app.AssistContent implements Parcelable {
+@Deprecated
+public class AssistContent implements Parcelable {
+    private boolean mIsAppProvidedIntent = false;
+    private Intent mIntent;
+    private String mStructuredData;
+    private ClipData mClipData;
+    private Uri mUri;
+    private final Bundle mExtras;
 
-    /** @hide */
     public AssistContent() {
+        mExtras = new Bundle();
     }
 
-    public AssistContent(Parcel in) {
-        super(in);
+    /**
+     * @hide
+     * Called by {@link android.app.ActivityThread} to set the default Intent based on
+     * {@link android.app.Activity#getIntent Activity.getIntent}.
+     *
+     * <p>Automatically populates {@link #mUri} if that Intent is an {@link Intent#ACTION_VIEW}
+     * of a web (http or https scheme) URI.</p>
+     */
+    public void setDefaultIntent(Intent intent) {
+        mIntent = intent;
+        setWebUri(null);
+        if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
+            Uri uri = intent.getData();
+            if (uri != null) {
+                if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) {
+                    setWebUri(uri);
+                }
+            }
+        }
     }
 
+    /**
+     * Sets the Intent associated with the content, describing the current top-level context of
+     * the activity.  If this contains a reference to a piece of data related to the activity,
+     * be sure to set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} so the accessibility
+     * service can access it.
+     */
+    public void setIntent(Intent intent) {
+        mIsAppProvidedIntent = true;
+        mIntent = intent;
+    }
+
+    /**
+     * Returns the current {@link #setIntent} if one is set, else the default Intent obtained from
+     * {@link android.app.Activity#getIntent Activity.getIntent}. Can be modified in-place.
+     */
     public Intent getIntent() {
-        return super.getIntent();
+        return mIntent;
+    }
+
+    /**
+     * Returns whether or not the current Intent was explicitly provided in
+     * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not,
+     * the Intent was automatically set based on
+     * {@link android.app.Activity#getIntent Activity.getIntent}.
+     */
+    public boolean isAppProvidedIntent() {
+        return mIsAppProvidedIntent;
+    }
+
+    /**
+     * Optional additional content items that are involved with
+     * the current UI.  Access to this content will be granted to the assistant as if you
+     * are sending it through an Intent with {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
+     */
+    public void setClipData(ClipData clip) {
+        mClipData = clip;
+    }
+
+    /**
+     * Return the current {@link #setClipData}, which you can modify in-place.
+     */
+    public ClipData getClipData() {
+        return mClipData;
+    }
+
+    /**
+     * Sets optional structured data regarding the content being viewed. The provided data
+     * must be a string represented with <a href="http://json-ld.org/">JSON-LD</a> using the
+     * <a href="http://schema.org/">schema.org</a> vocabulary.
+     */
+    public void setStructuredData(String structuredData) {
+        mStructuredData = structuredData;
+    }
+
+    /**
+     * Returns the current {@link #setStructuredData}.
+     */
+    public String getStructuredData() {
+        return mStructuredData;
+    }
+
+    /**
+     * Set a web URI associated with the current data being shown to the user.
+     * This URI could be opened in a web browser, or in the app as an
+     * {@link Intent#ACTION_VIEW} Intent, to show the same data that is currently
+     * being displayed by it.  The URI here should be something that is transportable
+     * off the device into other environments to acesss the same data as is currently
+     * being shown in the app; if the app does not have such a representation, it should
+     * leave the null and only report the local intent and clip data.
+     */
+    public void setWebUri(Uri uri) {
+        mUri = uri;
+    }
+
+    /**
+     * Return the content's web URI as per {@link #setWebUri(android.net.Uri)}, or null if
+     * there is none.
+     */
+    public Uri getWebUri() {
+        return mUri;
+    }
+
+    /**
+     * Return Bundle for extra vendor-specific data that can be modified and examined.
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    AssistContent(Parcel in) {
+        if (in.readInt() != 0) {
+            mIntent = Intent.CREATOR.createFromParcel(in);
+        }
+        if (in.readInt() != 0) {
+            mClipData = ClipData.CREATOR.createFromParcel(in);
+        }
+        if (in.readInt() != 0) {
+            mUri = Uri.CREATOR.createFromParcel(in);
+        }
+        if (in.readInt() != 0) {
+            mStructuredData = in.readString();
+        }
+        mIsAppProvidedIntent = in.readInt() == 1;
+        mExtras = in.readBundle();
+    }
+
+    void writeToParcelInternal(Parcel dest, int flags) {
+        if (mIntent != null) {
+            dest.writeInt(1);
+            mIntent.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mClipData != null) {
+            dest.writeInt(1);
+            mClipData.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mUri != null) {
+            dest.writeInt(1);
+            mUri.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mStructuredData != null) {
+            dest.writeInt(1);
+            dest.writeString(mStructuredData);
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
+        dest.writeBundle(mExtras);
     }
 
     @Override
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 1677e95..1a04895 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1,28 +1,1038 @@
 package android.app.assist;
 
 import android.app.Activity;
+import android.content.ComponentName;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PooledStringReader;
+import android.os.PooledStringWriter;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewAssistStructure;
+import android.view.ViewRootImpl;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+import java.util.ArrayList;
 
 /**
- * New home for AssistStructure.
+ * Assist data automatically created by the platform's implementation
+ * of {@link android.app.Activity#onProvideAssistData}.
  */
-public final class AssistStructure extends android.app.AssistStructure implements Parcelable {
+public class AssistStructure implements Parcelable {
+    static final String TAG = "AssistStructure";
 
-    public AssistStructure() {
+    boolean mHaveData;
+
+    ComponentName mActivityComponent;
+
+    final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
+
+    final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
+
+    SendChannel mSendChannel;
+    IBinder mReceiveChannel;
+
+    Rect mTmpRect = new Rect();
+
+    static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
+    static final String DESCRIPTOR = "android.app.AssistStructure";
+
+    final class SendChannel extends Binder {
+        @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                throws RemoteException {
+            if (code == TRANSACTION_XFER) {
+                data.enforceInterface(DESCRIPTOR);
+                writeContentToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+                return true;
+            } else {
+                return super.onTransact(code, data, reply, flags);
+            }
+        }
+    }
+
+    final static class ViewNodeText {
+        CharSequence mText;
+        int mTextSelectionStart;
+        int mTextSelectionEnd;
+        int mTextColor;
+        int mTextBackgroundColor;
+        float mTextSize;
+        int mTextStyle;
+        String mHint;
+
+        ViewNodeText() {
+        }
+
+        ViewNodeText(Parcel in) {
+            mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+            mTextSelectionStart = in.readInt();
+            mTextSelectionEnd = in.readInt();
+            mTextColor = in.readInt();
+            mTextBackgroundColor = in.readInt();
+            mTextSize = in.readFloat();
+            mTextStyle = in.readInt();
+            mHint = in.readString();
+        }
+
+        void writeToParcel(Parcel out) {
+            TextUtils.writeToParcel(mText, out, 0);
+            out.writeInt(mTextSelectionStart);
+            out.writeInt(mTextSelectionEnd);
+            out.writeInt(mTextColor);
+            out.writeInt(mTextBackgroundColor);
+            out.writeFloat(mTextSize);
+            out.writeInt(mTextStyle);
+            out.writeString(mHint);
+        }
+    }
+
+    /**
+     * Describes a window in the assist data.
+     */
+    static public class WindowNode {
+        final int mX;
+        final int mY;
+        final int mWidth;
+        final int mHeight;
+        final CharSequence mTitle;
+        final int mDisplayId;
+        final ViewNode mRoot;
+
+        WindowNode(AssistStructure assist, ViewRootImpl root) {
+            View view = root.getView();
+            Rect rect = new Rect();
+            view.getBoundsOnScreen(rect);
+            mX = rect.left - view.getLeft();
+            mY = rect.top - view.getTop();
+            mWidth = rect.width();
+            mHeight = rect.height();
+            mTitle = root.getTitle();
+            mDisplayId = root.getDisplayId();
+            mRoot = new ViewNode();
+            ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
+            if ((root.getWindowFlags()& WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+                // This is a secure window, so it doesn't want a screenshot, and that
+                // means we should also not copy out its view hierarchy.
+                view.onProvideStructure(builder);
+                builder.setAssistBlocked(true);
+                return;
+            }
+            view.dispatchProvideStructure(builder);
+        }
+
+        WindowNode(Parcel in, PooledStringReader preader) {
+            mX = in.readInt();
+            mY = in.readInt();
+            mWidth = in.readInt();
+            mHeight = in.readInt();
+            mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+            mDisplayId = in.readInt();
+            mRoot = new ViewNode(in, preader);
+        }
+
+        void writeToParcel(Parcel out, PooledStringWriter pwriter) {
+            out.writeInt(mX);
+            out.writeInt(mY);
+            out.writeInt(mWidth);
+            out.writeInt(mHeight);
+            TextUtils.writeToParcel(mTitle, out, 0);
+            out.writeInt(mDisplayId);
+            mRoot.writeToParcel(out, pwriter);
+        }
+
+        /**
+         * Returns the left edge of the window, in pixels, relative to the left
+         * edge of the screen.
+         */
+        public int getLeft() {
+            return mX;
+        }
+
+        /**
+         * Returns the top edge of the window, in pixels, relative to the top
+         * edge of the screen.
+         */
+        public int getTop() {
+            return mY;
+        }
+
+        /**
+         * Returns the total width of the window in pixels.
+         */
+        public int getWidth() {
+            return mWidth;
+        }
+
+        /**
+         * Returns the total height of the window in pixels.
+         */
+        public int getHeight() {
+            return mHeight;
+        }
+
+        /**
+         * Returns the title associated with the window, if it has one.
+         */
+        public CharSequence getTitle() {
+            return mTitle;
+        }
+
+        /**
+         * Returns the ID of the display this window is on, for use with
+         * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}.
+         */
+        public int getDisplayId() {
+            return mDisplayId;
+        }
+
+        /**
+         * Returns the {@link ViewNode} containing the root content of the window.
+         */
+        public ViewNode getRootViewNode() {
+            return mRoot;
+        }
+    }
+
+    /**
+     * Describes a single view in the assist data.
+     */
+    static public class ViewNode {
+        /**
+         * Magic value for text color that has not been defined, which is very unlikely
+         * to be confused with a real text color.
+         */
+        public static final int TEXT_COLOR_UNDEFINED = 1;
+
+        public static final int TEXT_STYLE_BOLD = 1<<0;
+        public static final int TEXT_STYLE_ITALIC = 1<<1;
+        public static final int TEXT_STYLE_UNDERLINE = 1<<2;
+        public static final int TEXT_STYLE_STRIKE_THRU = 1<<3;
+
+        int mId;
+        String mIdPackage;
+        String mIdType;
+        String mIdEntry;
+        int mX;
+        int mY;
+        int mScrollX;
+        int mScrollY;
+        int mWidth;
+        int mHeight;
+
+        static final int FLAGS_DISABLED = 0x00000001;
+        static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
+        static final int FLAGS_FOCUSABLE = 0x00000010;
+        static final int FLAGS_FOCUSED = 0x00000020;
+        static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000;
+        static final int FLAGS_SELECTED = 0x00000040;
+        static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
+        static final int FLAGS_ACTIVATED = 0x40000000;
+        static final int FLAGS_CHECKABLE = 0x00000100;
+        static final int FLAGS_CHECKED = 0x00000200;
+        static final int FLAGS_CLICKABLE = 0x00004000;
+        static final int FLAGS_LONG_CLICKABLE = 0x00200000;
+        static final int FLAGS_CONTEXT_CLICKABLE = 0x00400000;
+
+        int mFlags;
+
+        String mClassName;
+        CharSequence mContentDescription;
+
+        ViewNodeText mText;
+        Bundle mExtras;
+
+        ViewNode[] mChildren;
+
+        ViewNode() {
+        }
+
+        ViewNode(Parcel in, PooledStringReader preader) {
+            mId = in.readInt();
+            if (mId != 0) {
+                mIdEntry = preader.readString();
+                if (mIdEntry != null) {
+                    mIdType = preader.readString();
+                    mIdPackage = preader.readString();
+                } else {
+                    mIdPackage = mIdType = null;
+                }
+            } else {
+                mIdPackage = mIdType = mIdEntry = null;
+            }
+            mX = in.readInt();
+            mY = in.readInt();
+            mScrollX = in.readInt();
+            mScrollY = in.readInt();
+            mWidth = in.readInt();
+            mHeight = in.readInt();
+            mFlags = in.readInt();
+            mClassName = preader.readString();
+            mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+            if (in.readInt() != 0) {
+                mText = new ViewNodeText(in);
+            } else {
+                mText = null;
+            }
+            mExtras = in.readBundle();
+            final int NCHILDREN = in.readInt();
+            if (NCHILDREN > 0) {
+                mChildren = new ViewNode[NCHILDREN];
+                for (int i=0; i<NCHILDREN; i++) {
+                    mChildren[i] = new ViewNode(in, preader);
+                }
+            } else {
+                mChildren = null;
+            }
+        }
+
+        void writeToParcel(Parcel out, PooledStringWriter pwriter) {
+            out.writeInt(mId);
+            if (mId != 0) {
+                pwriter.writeString(mIdEntry);
+                if (mIdEntry != null) {
+                    pwriter.writeString(mIdType);
+                    pwriter.writeString(mIdPackage);
+                }
+            }
+            out.writeInt(mX);
+            out.writeInt(mY);
+            out.writeInt(mScrollX);
+            out.writeInt(mScrollY);
+            out.writeInt(mWidth);
+            out.writeInt(mHeight);
+            out.writeInt(mFlags);
+            pwriter.writeString(mClassName);
+            TextUtils.writeToParcel(mContentDescription, out, 0);
+            if (mText != null) {
+                out.writeInt(1);
+                mText.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+            }
+            out.writeBundle(mExtras);
+            if (mChildren != null) {
+                final int NCHILDREN = mChildren.length;
+                out.writeInt(NCHILDREN);
+                for (int i=0; i<NCHILDREN; i++) {
+                    mChildren[i].writeToParcel(out, pwriter);
+                }
+            } else {
+                out.writeInt(0);
+            }
+        }
+
+        /**
+         * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
+         */
+        public int getId() {
+            return mId;
+        }
+
+        /**
+         * If {@link #getId()} is a resource identifier, this is the package name of that
+         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
+         * for more information.
+         */
+        public String getIdPackage() {
+            return mIdPackage;
+        }
+
+        /**
+         * If {@link #getId()} is a resource identifier, this is the type name of that
+         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
+         * for more information.
+         */
+        public String getIdType() {
+            return mIdType;
+        }
+
+        /**
+         * If {@link #getId()} is a resource identifier, this is the entry name of that
+         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
+         * for more information.
+         */
+        public String getIdEntry() {
+            return mIdEntry;
+        }
+
+        /**
+         * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
+         */
+        public int getLeft() {
+            return mX;
+        }
+
+        /**
+         * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
+         */
+        public int getTop() {
+            return mY;
+        }
+
+        /**
+         * Returns the current X scroll offset of this view, as per
+         * {@link android.view.View#getScrollX() View.getScrollX()}.
+         */
+        public int getScrollX() {
+            return mScrollX;
+        }
+
+        /**
+         * Returns the current Y scroll offset of this view, as per
+         * {@link android.view.View#getScrollX() View.getScrollY()}.
+         */
+        public int getScrollY() {
+            return mScrollY;
+        }
+
+        /**
+         * Returns the width of this view, in pixels.
+         */
+        public int getWidth() {
+            return mWidth;
+        }
+
+        /**
+         * Returns the height of this view, in pixels.
+         */
+        public int getHeight() {
+            return mHeight;
+        }
+
+        /**
+         * Returns the visibility mode of this view, as per
+         * {@link android.view.View#getVisibility() View.getVisibility()}.
+         */
+        public int getVisibility() {
+            return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
+        }
+
+        /**
+         * Returns true if assist data has been blocked starting at this node in the hierarchy.
+         */
+        public boolean isAssistBlocked() {
+            return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0;
+        }
+
+        /**
+         * Returns true if this node is in an enabled state.
+         */
+        public boolean isEnabled() {
+            return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
+        }
+
+        /**
+         * Returns true if this node is clickable by the user.
+         */
+        public boolean isClickable() {
+            return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
+        }
+
+        /**
+         * Returns true if this node can take input focus.
+         */
+        public boolean isFocusable() {
+            return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
+        }
+
+        /**
+         * Returns true if this node currently had input focus at the time that the
+         * structure was collected.
+         */
+        public boolean isFocused() {
+            return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
+        }
+
+        /**
+         * Returns true if this node currently had accessibility focus at the time that the
+         * structure was collected.
+         */
+        public boolean isAccessibilityFocused() {
+            return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
+        }
+
+        /**
+         * Returns true if this node represents something that is checkable by the user.
+         */
+        public boolean isCheckable() {
+            return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
+        }
+
+        /**
+         * Returns true if this node is currently in a checked state.
+         */
+        public boolean isChecked() {
+            return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
+        }
+
+        /**
+         * Returns true if this node has currently been selected by the user.
+         */
+        public boolean isSelected() {
+            return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
+        }
+
+        /**
+         * Returns true if this node has currently been activated by the user.
+         */
+        public boolean isActivated() {
+            return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
+        }
+
+        /**
+         * Returns true if this node is something the user can perform a long click/press on.
+         */
+        public boolean isLongClickable() {
+            return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
+        }
+
+        /**
+         * Returns true if this node is something the user can perform a context click on.
+         */
+        public boolean isContextClickable() {
+            return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
+        }
+
+        /**
+         * Returns the class name of the node's implementation, indicating its behavior.
+         * For example, a button will report "android.widget.Button" meaning it behaves
+         * like a {@link android.widget.Button}.
+         */
+        public String getClassName() {
+            return mClassName;
+        }
+
+        /**
+         * Returns any content description associated with the node, which semantically describes
+         * its purpose for accessibility and other uses.
+         */
+        public CharSequence getContentDescription() {
+            return mContentDescription;
+        }
+
+        /**
+         * Returns any text associated with the node that is displayed to the user, or null
+         * if there is none.
+         */
+        public CharSequence getText() {
+            return mText != null ? mText.mText : null;
+        }
+
+        /**
+         * If {@link #getText()} is non-null, this is where the current selection starts.
+         */
+        public int getTextSelectionStart() {
+            return mText != null ? mText.mTextSelectionStart : -1;
+        }
+
+        /**
+         * If {@link #getText()} is non-null, this is where the current selection starts.
+         * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
+         * indicating the cursor position.
+         */
+        public int getTextSelectionEnd() {
+            return mText != null ? mText.mTextSelectionEnd : -1;
+        }
+
+        /**
+         * If {@link #getText()} is non-null, this is the main text color associated with it.
+         * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
+         * Note that the text may also contain style spans that modify the color of specific
+         * parts of the text.
+         */
+        public int getTextColor() {
+            return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
+        }
+
+        /**
+         * If {@link #getText()} is non-null, this is the main text background color associated
+         * with it.
+         * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
+         * Note that the text may also contain style spans that modify the color of specific
+         * parts of the text.
+         */
+        public int getTextBackgroundColor() {
+            return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
+        }
+
+        /**
+         * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
+         * with it.
+         * Note that the text may also contain style spans that modify the size of specific
+         * parts of the text.
+         */
+        public float getTextSize() {
+            return mText != null ? mText.mTextSize : 0;
+        }
+
+        /**
+         * If {@link #getText()} is non-null, this is the main text style associated
+         * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
+         * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
+         * {@link #TEXT_STYLE_UNDERLINE}.
+         * Note that the text may also contain style spans that modify the style of specific
+         * parts of the text.
+         */
+        public int getTextStyle() {
+            return mText != null ? mText.mTextStyle : 0;
+        }
+
+        /**
+         * Return additional hint text associated with the node; this is typically used with
+         * a node that takes user input, describing to the user what the input means.
+         */
+        public String getHint() {
+            return mText != null ? mText.mHint : null;
+        }
+
+        /**
+         * Return a Bundle containing optional vendor-specific extension information.
+         */
+        public Bundle getExtras() {
+            return mExtras;
+        }
+
+        /**
+         * Return the number of children this node has.
+         */
+        public int getChildCount() {
+            return mChildren != null ? mChildren.length : 0;
+        }
+
+        /**
+         * Return a child of this node, given an index value from 0 to
+         * {@link #getChildCount()}-1.
+         */
+        public ViewNode getChildAt(int index) {
+            return mChildren[index];
+        }
+    }
+
+    static class ViewNodeBuilder extends ViewAssistStructure {
+        final AssistStructure mAssist;
+        final ViewNode mNode;
+        final boolean mAsync;
+
+        ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
+            mAssist = assist;
+            mNode = node;
+            mAsync = async;
+        }
+
+        @Override
+        public void setId(int id, String packageName, String typeName, String entryName) {
+            mNode.mId = id;
+            mNode.mIdPackage = packageName;
+            mNode.mIdType = typeName;
+            mNode.mIdEntry = entryName;
+        }
+
+        @Override
+        public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
+            mNode.mX = left;
+            mNode.mY = top;
+            mNode.mScrollX = scrollX;
+            mNode.mScrollY = scrollY;
+            mNode.mWidth = width;
+            mNode.mHeight = height;
+        }
+
+        @Override
+        public void setVisibility(int visibility) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_VISIBILITY_MASK) | visibility;
+        }
+
+        @Override
+        public void setAssistBlocked(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
+                    | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED);
+        }
+
+        @Override
+        public void setEnabled(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
+                    | (state ? 0 : ViewNode.FLAGS_DISABLED);
+        }
+
+        @Override
+        public void setClickable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CLICKABLE)
+                    | (state ? ViewNode.FLAGS_CLICKABLE : 0);
+        }
+
+        @Override
+        public void setLongClickable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_LONG_CLICKABLE)
+                    | (state ? ViewNode.FLAGS_LONG_CLICKABLE : 0);
+        }
+
+        @Override
+        public void setContextClickable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE)
+                    | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0);
+        }
+
+        @Override
+        public void setFocusable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
+                    | (state ? ViewNode.FLAGS_FOCUSABLE : 0);
+        }
+
+        @Override
+        public void setFocused(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSED)
+                    | (state ? ViewNode.FLAGS_FOCUSED : 0);
+        }
+
+        @Override
+        public void setAccessibilityFocused(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACCESSIBILITY_FOCUSED)
+                    | (state ? ViewNode.FLAGS_ACCESSIBILITY_FOCUSED : 0);
+        }
+
+        @Override
+        public void setCheckable(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKABLE)
+                    | (state ? ViewNode.FLAGS_CHECKABLE : 0);
+        }
+
+        @Override
+        public void setChecked(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CHECKED)
+                    | (state ? ViewNode.FLAGS_CHECKED : 0);
+        }
+
+        @Override
+        public void setSelected(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_SELECTED)
+                    | (state ? ViewNode.FLAGS_SELECTED : 0);
+        }
+
+        @Override
+        public void setActivated(boolean state) {
+            mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ACTIVATED)
+                    | (state ? ViewNode.FLAGS_ACTIVATED : 0);
+        }
+
+        @Override
+        public void setClassName(String className) {
+            mNode.mClassName = className;
+        }
+
+        @Override
+        public void setContentDescription(CharSequence contentDescription) {
+            mNode.mContentDescription = contentDescription;
+        }
+
+        private final ViewNodeText getNodeText() {
+            if (mNode.mText != null) {
+                return mNode.mText;
+            }
+            mNode.mText = new ViewNodeText();
+            return mNode.mText;
+        }
+
+        @Override
+        public void setText(CharSequence text) {
+            ViewNodeText t = getNodeText();
+            t.mText = text;
+            t.mTextSelectionStart = t.mTextSelectionEnd = -1;
+        }
+
+        @Override
+        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
+            ViewNodeText t = getNodeText();
+            t.mText = text;
+            t.mTextSelectionStart = selectionStart;
+            t.mTextSelectionEnd = selectionEnd;
+        }
+
+        @Override
+        public void setTextStyle(float size, int fgColor, int bgColor, int style) {
+            ViewNodeText t = getNodeText();
+            t.mTextColor = fgColor;
+            t.mTextBackgroundColor = bgColor;
+            t.mTextSize = size;
+            t.mTextStyle = style;
+        }
+
+        @Override
+        public void setHint(CharSequence hint) {
+            getNodeText().mHint = hint != null ? hint.toString() : null;
+        }
+
+        @Override
+        public CharSequence getText() {
+            return mNode.mText != null ? mNode.mText.mText : null;
+        }
+
+        @Override
+        public int getTextSelectionStart() {
+            return mNode.mText != null ? mNode.mText.mTextSelectionStart : -1;
+        }
+
+        @Override
+        public int getTextSelectionEnd() {
+            return mNode.mText != null ? mNode.mText.mTextSelectionEnd : -1;
+        }
+
+        @Override
+        public CharSequence getHint() {
+            return mNode.mText != null ? mNode.mText.mHint : null;
+        }
+
+        @Override
+        public Bundle getExtras() {
+            if (mNode.mExtras != null) {
+                return mNode.mExtras;
+            }
+            mNode.mExtras = new Bundle();
+            return mNode.mExtras;
+        }
+
+        @Override
+        public boolean hasExtras() {
+            return mNode.mExtras != null;
+        }
+
+        @Override
+        public void setChildCount(int num) {
+            mNode.mChildren = new ViewNode[num];
+        }
+
+        @Override
+        public int addChildCount(int num) {
+            if (mNode.mChildren == null) {
+                setChildCount(num);
+                return 0;
+            }
+            final int start = mNode.mChildren.length;
+            ViewNode[] newArray = new ViewNode[start + num];
+            System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
+            mNode.mChildren = newArray;
+            return start;
+        }
+
+        @Override
+        public int getChildCount() {
+            return mNode.mChildren != null ? mNode.mChildren.length : 0;
+        }
+
+        @Override
+        public ViewAssistStructure newChild(int index) {
+            ViewNode node = new ViewNode();
+            mNode.mChildren[index] = node;
+            return new ViewNodeBuilder(mAssist, node, false);
+        }
+
+        @Override
+        public ViewAssistStructure asyncNewChild(int index) {
+            synchronized (mAssist) {
+                ViewNode node = new ViewNode();
+                mNode.mChildren[index] = node;
+                ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
+                mAssist.mPendingAsyncChildren.add(builder);
+                return builder;
+            }
+        }
+
+        @Override
+        public void asyncCommit() {
+            synchronized (mAssist) {
+                if (!mAsync) {
+                    throw new IllegalStateException("Child " + this
+                            + " was not created with ViewAssistStructure.asyncNewChild");
+                }
+                if (!mAssist.mPendingAsyncChildren.remove(this)) {
+                    throw new IllegalStateException("Child " + this + " already committed");
+                }
+                mAssist.notifyAll();
+            }
+        }
+
+        @Override
+        public Rect getTempRect() {
+            return mAssist.mTmpRect;
+        }
     }
 
     /** @hide */
     public AssistStructure(Activity activity) {
-        super(activity);
+        mHaveData = true;
+        mActivityComponent = activity.getComponentName();
+        ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
+                activity.getActivityToken());
+        for (int i=0; i<views.size(); i++) {
+            ViewRootImpl root = views.get(i);
+            mWindowNodes.add(new WindowNode(this, root));
+        }
     }
 
-    AssistStructure(Parcel in) {
-        super(in);
+    public AssistStructure() {
+        mHaveData = true;
+        mActivityComponent = null;
     }
 
+    /** @hide */
+    public AssistStructure(Parcel in) {
+        mReceiveChannel = in.readStrongBinder();
+    }
+
+    /** @hide */
+    public void dump() {
+        Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString());
+        final int N = getWindowNodeCount();
+        for (int i=0; i<N; i++) {
+            WindowNode node = getWindowNodeAt(i);
+            Log.i(TAG, "Window #" + i + " [" + node.getLeft() + "," + node.getTop()
+                    + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getTitle());
+            dump("  ", node.getRootViewNode());
+        }
+    }
+
+    void dump(String prefix, ViewNode node) {
+        Log.i(TAG, prefix + "View [" + node.getLeft() + "," + node.getTop()
+                + " " + node.getWidth() + "x" + node.getHeight() + "]" + " " + node.getClassName());
+        int id = node.getId();
+        if (id != 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(prefix); sb.append("  ID: #"); sb.append(Integer.toHexString(id));
+            String entry = node.getIdEntry();
+            if (entry != null) {
+                String type = node.getIdType();
+                String pkg = node.getIdPackage();
+                sb.append(" "); sb.append(pkg); sb.append(":"); sb.append(type);
+                sb.append("/"); sb.append(entry);
+            }
+            Log.i(TAG, sb.toString());
+        }
+        int scrollX = node.getScrollX();
+        int scrollY = node.getScrollY();
+        if (scrollX != 0 || scrollY != 0) {
+            Log.i(TAG, prefix + "  Scroll: " + scrollX + "," + scrollY);
+        }
+        CharSequence contentDescription = node.getContentDescription();
+        if (contentDescription != null) {
+            Log.i(TAG, prefix + "  Content description: " + contentDescription);
+        }
+        CharSequence text = node.getText();
+        if (text != null) {
+            Log.i(TAG, prefix + "  Text (sel " + node.getTextSelectionStart() + "-"
+                    + node.getTextSelectionEnd() + "): " + text);
+            Log.i(TAG, prefix + "  Text size: " + node.getTextSize() + " , style: #"
+                    + node.getTextStyle());
+            Log.i(TAG, prefix + "  Text color fg: #" + Integer.toHexString(node.getTextColor())
+                    + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
+        }
+        String hint = node.getHint();
+        if (hint != null) {
+            Log.i(TAG, prefix + "  Hint: " + hint);
+        }
+        Bundle extras = node.getExtras();
+        if (extras != null) {
+            Log.i(TAG, prefix + "  Extras: " + extras);
+        }
+        final int NCHILDREN = node.getChildCount();
+        if (NCHILDREN > 0) {
+            Log.i(TAG, prefix + "  Children:");
+            String cprefix = prefix + "    ";
+            for (int i=0; i<NCHILDREN; i++) {
+                ViewNode cnode = node.getChildAt(i);
+                dump(cprefix, cnode);
+            }
+        }
+    }
+
+    /**
+     * Return the activity this AssistStructure came from.
+     */
+    public ComponentName getActivityComponent() {
+        ensureData();
+        return mActivityComponent;
+    }
+
+    /**
+     * Return the number of window contents that have been collected in this assist data.
+     */
+    public int getWindowNodeCount() {
+        ensureData();
+        return mWindowNodes.size();
+    }
+
+    /**
+     * Return one of the windows in the assist data.
+     * @param index Which window to retrieve, may be 0 to {@link #getWindowNodeCount()}-1.
+     */
     public WindowNode getWindowNodeAt(int index) {
-        return super.getWindowNodeAt(index);
+        ensureData();
+        return mWindowNodes.get(index);
+    }
+
+    /** @hide */
+    public void ensureData() {
+        if (mHaveData) {
+            return;
+        }
+        mHaveData = true;
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(DESCRIPTOR);
+        try {
+            mReceiveChannel.transact(TRANSACTION_XFER, data, reply, 0);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failure reading AssistStructure data", e);
+            return;
+        }
+        readContentFromParcel(reply);
+        data.recycle();
+        reply.recycle();
+    }
+
+    void writeContentToParcel(Parcel out, int flags) {
+        // First make sure all content has been created.
+        boolean skipStructure = false;
+        synchronized (this) {
+            long endTime = SystemClock.uptimeMillis() + 5000;
+            long now;
+            while (mPendingAsyncChildren.size() > 0 && (now=SystemClock.uptimeMillis()) < endTime) {
+                try {
+                    wait(endTime-now);
+                } catch (InterruptedException e) {
+                }
+            }
+            if (mPendingAsyncChildren.size() > 0) {
+                // We waited too long, assume none of the assist structure is valid.
+                skipStructure = true;
+            }
+        }
+        int start = out.dataPosition();
+        PooledStringWriter pwriter = new PooledStringWriter(out);
+        ComponentName.writeToParcel(mActivityComponent, out);
+        final int N = skipStructure ? 0 : mWindowNodes.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            mWindowNodes.get(i).writeToParcel(out, pwriter);
+        }
+        pwriter.finish();
+        Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes");
+    }
+
+    void readContentFromParcel(Parcel in) {
+        PooledStringReader preader = new PooledStringReader(in);
+        mActivityComponent = ComponentName.readFromParcel(in);
+        final int N = in.readInt();
+        for (int i=0; i<N; i++) {
+            mWindowNodes.add(new WindowNode(in, preader));
+        }
+        //dump();
     }
 
     public int describeContents() {
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 8a31390..9113426 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -77,6 +77,12 @@
     public abstract boolean isAppIdle(String packageName, int userId);
 
     /**
+     * @return True if currently app idle parole mode is on.  This means all idle apps are allow to
+     * run for a short period of time.
+     */
+    public abstract boolean isAppIdleParoleOn();
+
+    /**
      * Sets up a listener for changes to packages being accessed.
      * @param listener A listener within the system process.
      */
@@ -90,8 +96,9 @@
     public abstract void removeAppIdleStateChangeListener(
             AppIdleStateChangeListener listener);
 
-    public interface AppIdleStateChangeListener {
-        void onAppIdleStateChanged(String packageName, int userId, boolean idle);
+    public static abstract class AppIdleStateChangeListener {
+        public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle);
+        public abstract void onParoleStateChanged(boolean isParoleOn);
     }
 
 }
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index d4dee5b..58bd5cd 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -274,6 +274,10 @@
                 } else {
                     syncResult.databaseError = true;
                 }
+            } catch (SecurityException e) {
+                AbstractThreadedSyncAdapter.this.onSecurityException(mAccount, mExtras,
+                        mAuthority, syncResult);
+                syncResult.databaseError = true;
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER);
 
@@ -319,6 +323,20 @@
             String authority, ContentProviderClient provider, SyncResult syncResult);
 
     /**
+     * Report that there was a security exception when opening the content provider
+     * prior to calling {@link #onPerformSync}.  This will be treated as a sync
+     * database failure.
+     *
+     * @param account the account that attempted to sync
+     * @param extras SyncAdapter-specific parameters
+     * @param authority the authority of the failed sync request
+     * @param syncResult SyncAdapter-specific parameters
+     */
+    public void onSecurityException(Account account, Bundle extras,
+            String authority, SyncResult syncResult) {
+    }
+
+    /**
      * Indicates that a sync operation has been canceled. This will be invoked on a separate
      * thread than the sync thread and so you must consider the multi-threaded implications
      * of the work that you do in this method.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2dbcde9..cb68d74 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -31,6 +31,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IPackagesProvider;
 import android.content.pm.IOnPermissionsChangeListener;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.InstrumentationInfo;
@@ -106,6 +107,8 @@
     void updatePermissionFlags(String permissionName, String packageName, int flagMask,
             int flagValues, int userId);
 
+    void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
+
     boolean shouldShowRequestPermissionRationale(String permissionName,
             String packageName, int userId);
 
@@ -303,18 +306,18 @@
      * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
      */
     int getComponentEnabledSetting(in ComponentName componentName, int userId);
-    
+
     /**
      * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
      */
     void setApplicationEnabledSetting(in String packageName, in int newState, int flags,
             int userId, String callingPackage);
-    
+
     /**
      * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
      */
     int getApplicationEnabledSetting(in String packageName, int userId);
-    
+
     /**
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
@@ -367,7 +370,7 @@
      */
      void freeStorage(in String volumeUuid, in long freeStorageSize,
              in IntentSender pi);
-     
+
     /**
      * Delete all the cache files in an applications cache directory
      * @param packageName The package name of the application whose cache
@@ -375,7 +378,7 @@
      * @param observer a callback used to notify when the deletion is finished.
      */
     void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer);
-    
+
     /**
      * Clear the user data directory of an application.
      * @param packageName The package name of the application whose cache
@@ -383,7 +386,7 @@
      * @param observer a callback used to notify when the operation is completed.
      */
     void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
-    
+
    /**
      * Get package statistics including the code, data and cache size for
      * an already installed package
@@ -393,7 +396,7 @@
      * retrieval of information is complete.
      */
     void getPackageSizeInfo(in String packageName, int userHandle, IPackageStatsObserver observer);
-    
+
     /**
      * Get a list of shared libraries that are available on the
      * system.
@@ -407,7 +410,7 @@
     FeatureInfo[] getSystemAvailableFeatures();
 
     boolean hasSystemFeature(String name);
-    
+
     void enterSafeMode();
     boolean isSafeMode();
     void systemReady();
@@ -498,4 +501,7 @@
 
     void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
     void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+
+    void grantDefaultPermissions(int userId);
+    void setCarrierAppPackagesProvider(in IPackagesProvider provider);
 }
diff --git a/core/java/android/content/pm/IPackagesProvider.aidl b/core/java/android/content/pm/IPackagesProvider.aidl
new file mode 100644
index 0000000..7d76c88
--- /dev/null
+++ b/core/java/android/content/pm/IPackagesProvider.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 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.content.pm;
+
+/** {@hide} */
+interface IPackagesProvider {
+    String[] getPackages(int userId);
+}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 27d14b3..a88b71c 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -628,7 +628,7 @@
     /**
      * <p>List of available high speed video size, fps range and max batch size configurations
      * supported by the camera device, in the format of (width, height, fps_min, fps_max, batch_size_max).</p>
-     * <p>When CONSTRAINED_HIGH_SPEED_VIDEO is supported in android.control.availableCapabilities,
+     * <p>When CONSTRAINED_HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities},
      * this metadata will list the supported high speed video size, fps range and max batch size
      * configurations. All the sizes listed in this configuration will be a subset of the sizes
      * reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes }
@@ -675,6 +675,7 @@
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      * @hide
      */
     public static final Key<android.hardware.camera2.params.HighSpeedVideoConfiguration[]> CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS =
@@ -2679,9 +2680,7 @@
      * <p>Camera devices will come in three flavors: LEGACY, LIMITED and FULL.</p>
      * <p>A FULL device will support below capabilities:</p>
      * <ul>
-     * <li>30fps operation at maximum resolution (== sensor resolution) is preferred, more than
-     *   20fps is required, for at least uncompressed YUV
-     *   output. ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains BURST_CAPTURE)</li>
+     * <li>BURST_CAPTURE capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains BURST_CAPTURE)</li>
      * <li>Per frame control ({@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} <code>==</code> PER_FRAME_CONTROL)</li>
      * <li>Manual sensor control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains MANUAL_SENSOR)</li>
      * <li>Manual post-processing control ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains
@@ -2689,7 +2688,7 @@
      * <li>Arbitrary cropping region ({@link CameraCharacteristics#SCALER_CROPPING_TYPE android.scaler.croppingType} <code>==</code> FREEFORM)</li>
      * <li>At least 3 processed (but not stalling) format output streams
      *   ({@link CameraCharacteristics#REQUEST_MAX_NUM_OUTPUT_PROC android.request.maxNumOutputProc} <code>&gt;=</code> 3)</li>
-     * <li>The required stream configuration defined in android.scaler.availableStreamConfigurations</li>
+     * <li>The required stream configurations defined in android.scaler.availableStreamConfigurations</li>
      * <li>The required exposure time range defined in {@link CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE android.sensor.info.exposureTimeRange}</li>
      * <li>The required maxFrameDuration defined in {@link CameraCharacteristics#SENSOR_INFO_MAX_FRAME_DURATION android.sensor.info.maxFrameDuration}</li>
      * </ul>
@@ -2709,23 +2708,11 @@
      * post-processing, arbitrary cropping regions, and has relaxed performance constraints.</p>
      * <p>Each higher level supports everything the lower level supports
      * in this order: FULL <code>&gt;</code> LIMITED <code>&gt;</code> LEGACY.</p>
-     * <p>A HIGH_RESOLUTION device is equivalent to a FULL device, except that:</p>
-     * <ul>
-     * <li>At least one output resolution of 8 megapixels or higher in uncompressed YUV is
-     *   supported at <code>&gt;=</code> 20 fps.</li>
-     * <li>Maximum-size (sensor resolution) uncompressed YUV is supported  at <code>&gt;=</code> 10
-     *   fps.</li>
-     * <li>For devices that list the RAW capability and support either RAW10 or RAW12 output,
-     *   maximum-resolution RAW10 or RAW12 capture will operate at least at the rate of
-     *   maximum-resolution YUV capture, and at least one supported output resolution of
-     *   8 megapixels or higher in RAW10 or RAW12 is supported <code>&gt;=</code> 20 fps.</li>
-     * </ul>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li>
      *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li>
-     *   <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION HIGH_RESOLUTION}</li>
      * </ul></p>
      * <p>This key is available on all devices.</p>
      *
@@ -2743,7 +2730,6 @@
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
      * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
-     * @see #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION
      */
     @PublicKey
     public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL =
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index c656fb8b..5a80585 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -531,37 +531,32 @@
     public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5;
 
     /**
-     * <p>The camera device supports capturing maximum-resolution
-     * images at &gt;= 20 frames per second, in at least the
-     * uncompressed YUV format, when post-processing settings
-     * are set to FAST.</p>
-     * <p>More specifically, this means that a size matching the
-     * camera device's active array size is listed as a
-     * supported size for the YUV_420_888 format in
-     * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP android.scaler.streamConfigurationMap}, the minimum frame
-     * duration for that format and size is &lt;= 1/20 s, and
-     * the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry
-     * lists at least one FPS range where the minimum FPS is</p>
-     * <blockquote>
-     * <p>= 1 / minimumFrameDuration for the maximum-size
-     * YUV_420_888 format.</p>
-     * </blockquote>
-     * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is
-     * guaranted to have a value between 0 and 4, inclusive.
-     * {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and
-     * {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} are also guaranteed
-     * to be <code>true</code> so burst capture with these two locks ON
-     * yields consistent image output.</p>
-     * <p>On a camera device that reports the HIGH_RESOLUTION hardware
-     * level, meaning the device supports very large capture sizes,
-     * BURST_CAPTURE means that at least 8-megapixel images can be
-     * captured at <code>&gt;=</code> 20 fps, and maximum-resolution images can be
-     * captured at <code>&gt;=</code> 10 fps.</p>
+     * <p>The camera device supports capturing high-resolution images at &gt;= 20 frames per
+     * second, in at least the uncompressed YUV format, when post-processing settings are set
+     * to FAST. Additionally, maximum-resolution images can be captured at &gt;= 10 frames
+     * per second.  Here, 'high resolution' means at least 8 megapixels, or the maximum
+     * resolution of the device, whichever is smaller.</p>
+     * <p>More specifically, this means that a size matching the camera device's active array
+     * size is listed as a supported size for the {@link android.graphics.ImageFormat#YUV_420_888 } format in either {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } or {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes },
+     * with a minimum frame duration for that format and size of either &lt;= 1/20 s, or
+     * &lt;= 1/10 s, respectively; and the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry
+     * lists at least one FPS range where the minimum FPS is &gt;= 1 / minimumFrameDuration
+     * for the maximum-size YUV_420_888 format.  If that maximum size is listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes },
+     * then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at
+     * least one resolution &gt;= 8 megapixels, with a minimum frame duration of &lt;= 1/20
+     * s.</p>
+     * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be captured at the same rate
+     * as the maximum-size YUV_420_888 resolution is.</p>
+     * <p>If the device supports the PRIVATE_REPROCESSING capability, then the same guarantees
+     * as for the YUV_420_888 format also apply to the {@link android.graphics.ImageFormat#PRIVATE } format.</p>
+     * <p>In addition, the {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} field is guaranted to have a value between 0
+     * and 4, inclusive. {@link CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE android.control.aeLockAvailable} and {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable}
+     * are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields
+     * consistent image output.</p>
      *
      * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
      * @see CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE
      * @see CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE
-     * @see CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP
      * @see CameraCharacteristics#SYNC_MAX_LATENCY
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
@@ -954,13 +949,6 @@
      */
     public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2;
 
-    /**
-     * <p>This camera device is capable of supporting advanced imaging applications at full rate,
-     * and additional high-resolution outputs at lower rates.</p>
-     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
-     */
-    public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3;
-
     //
     // Enumeration values for CameraCharacteristics#SYNC_MAX_LATENCY
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 9fa6687..75289f7 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -398,7 +398,7 @@
 
     @Override
     public int hashCode() {
-        return HashCodeHelpers.hashCode(mSettings, mSurfaceSet, mUserTag);
+        return HashCodeHelpers.hashCodeGeneric(mSettings, mSurfaceSet, mUserTag);
     }
 
     public static final Parcelable.Creator<CaptureRequest> CREATOR =
@@ -1759,11 +1759,24 @@
      * 16:9 aspect ratio, the primary image will be cropped vertically (letterbox) to
      * generate the thumbnail image. The thumbnail image will always have a smaller Field
      * Of View (FOV) than the primary image when aspect ratios differ.</p>
+     * <p>When an {@link CaptureRequest#JPEG_ORIENTATION android.jpeg.orientation} of non-zero degree is requested,
+     * the camera device will handle thumbnail rotation in one of the following ways:</p>
+     * <ul>
+     * <li>Set the {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}
+     *   and keep jpeg and thumbnail image data unrotated.</li>
+     * <li>Rotate the jpeg and thumbnail image data and not set
+     *   {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}. In this
+     *   case, LIMITED or FULL hardware level devices will report rotated thumnail size in
+     *   capture result, so the width and height will be interchanged if 90 or 270 degree
+     *   orientation is requested. LEGACY device will always report unrotated thumbnail
+     *   size.</li>
+     * </ul>
      * <p><b>Range of valid values:</b><br>
      * {@link CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES android.jpeg.availableThumbnailSizes}</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES
+     * @see CaptureRequest#JPEG_ORIENTATION
      */
     @PublicKey
     public static final Key<android.util.Size> JPEG_THUMBNAIL_SIZE =
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index b1fb615..1d31109 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2314,11 +2314,24 @@
      * 16:9 aspect ratio, the primary image will be cropped vertically (letterbox) to
      * generate the thumbnail image. The thumbnail image will always have a smaller Field
      * Of View (FOV) than the primary image when aspect ratios differ.</p>
+     * <p>When an {@link CaptureRequest#JPEG_ORIENTATION android.jpeg.orientation} of non-zero degree is requested,
+     * the camera device will handle thumbnail rotation in one of the following ways:</p>
+     * <ul>
+     * <li>Set the {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}
+     *   and keep jpeg and thumbnail image data unrotated.</li>
+     * <li>Rotate the jpeg and thumbnail image data and not set
+     *   {@link android.media.ExifInterface#TAG_ORIENTATION EXIF orientation flag}. In this
+     *   case, LIMITED or FULL hardware level devices will report rotated thumnail size in
+     *   capture result, so the width and height will be interchanged if 90 or 270 degree
+     *   orientation is requested. LEGACY device will always report unrotated thumbnail
+     *   size.</li>
+     * </ul>
      * <p><b>Range of valid values:</b><br>
      * {@link CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES android.jpeg.availableThumbnailSizes}</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#JPEG_AVAILABLE_THUMBNAIL_SIZES
+     * @see CaptureRequest#JPEG_ORIENTATION
      */
     @PublicKey
     public static final Key<android.util.Size> JPEG_THUMBNAIL_SIZE =
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 10dd8ae..7e50fd9 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -842,11 +842,19 @@
                 CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
         ReprocessFormatsMap inputOutputFormatsMap = getBase(
                 CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP);
-
+        int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+        boolean listHighResolution = false;
+        for (int capability : capabilities) {
+            if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
+                listHighResolution = true;
+                break;
+            }
+        }
         return new StreamConfigurationMap(
                 configurations, minFrameDurations, stallDurations,
                 depthConfigurations, depthMinFrameDurations, depthStallDurations,
-                highSpeedVideoConfigurations, inputOutputFormatsMap);
+                highSpeedVideoConfigurations, inputOutputFormatsMap,
+                listHighResolution);
     }
 
     private <T> Integer getMaxRegions(Key<T> key) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 2fb3203..e786707 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -605,6 +605,14 @@
         return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceType(surface));
     }
 
+    /**
+     * Query the surface for its currently configured dataspace
+     */
+    public static int detectSurfaceDataspace(Surface surface) throws BufferQueueAbandonedException {
+        checkNotNull(surface);
+        return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface));
+    }
+
     static void configureSurface(Surface surface, int width, int height,
                                  int pixelFormat) throws BufferQueueAbandonedException {
         checkNotNull(surface);
@@ -702,6 +710,8 @@
 
     private static native int nativeDetectSurfaceType(Surface surface);
 
+    private static native int nativeDetectSurfaceDataspace(Surface surface);
+
     private static native int nativeDetectSurfaceDimens(Surface surface,
             /*out*/int[/*2*/] dimens);
 
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index c6ea488..639ad60 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -20,14 +20,16 @@
 import android.graphics.PixelFormat;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.utils.HashCodeHelpers;
+import android.hardware.camera2.utils.SurfaceUtils;
 import android.hardware.camera2.legacy.LegacyCameraDevice;
 import android.hardware.camera2.legacy.LegacyMetadataMapper;
-import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
 import android.view.Surface;
 import android.util.Range;
 import android.util.Size;
+import android.util.SparseIntArray;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -79,7 +81,8 @@
      * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration}
      * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if
      *        camera device does not support high speed video recording
-     *
+     * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE
+     *        and thus needs a separate list of slow high-resolution output sizes
      * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations
      *         were {@code null} or any subelements were {@code null}
      *
@@ -93,10 +96,12 @@
             StreamConfigurationDuration[] depthMinFrameDurations,
             StreamConfigurationDuration[] depthStallDurations,
             HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
-            ReprocessFormatsMap inputOutputFormatsMap) {
+            ReprocessFormatsMap inputOutputFormatsMap,
+            boolean listHighResolution) {
         mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
         mMinFrameDurations = checkArrayElementsNotNull(minFrameDurations, "minFrameDurations");
         mStallDurations = checkArrayElementsNotNull(stallDurations, "stallDurations");
+        mListHighResolution = listHighResolution;
 
         if (depthConfigurations == null) {
             mDepthConfigurations = new StreamConfiguration[0];
@@ -120,15 +125,27 @@
 
         // For each format, track how many sizes there are available to configure
         for (StreamConfiguration config : configurations) {
-            HashMap<Integer, Integer> map = config.isOutput() ? mOutputFormats : mInputFormats;
-
-            Integer count = map.get(config.getFormat());
-
-            if (count == null) {
-                count = 0;
+            int fmt = config.getFormat();
+            SparseIntArray map = null;
+            if (config.isOutput()) {
+                mAllOutputFormats.put(fmt, mAllOutputFormats.get(fmt) + 1);
+                long duration = 0;
+                if (mListHighResolution) {
+                    for (StreamConfigurationDuration configurationDuration : mMinFrameDurations) {
+                        if (configurationDuration.getFormat() == fmt &&
+                                configurationDuration.getWidth() == config.getSize().getWidth() &&
+                                configurationDuration.getHeight() == config.getSize().getHeight()) {
+                            duration = configurationDuration.getDuration();
+                            break;
+                        }
+                    }
+                }
+                map = duration <= DURATION_20FPS_NS ?
+                        mOutputFormats : mHighResOutputFormats;
+            } else {
+                map = mInputFormats;
             }
-
-            map.put(config.getFormat(), count + 1);
+            map.put(fmt, map.get(fmt) + 1);
         }
 
         // For each depth format, track how many sizes there are available to configure
@@ -138,16 +155,11 @@
                 continue;
             }
 
-            Integer count = mDepthOutputFormats.get(config.getFormat());
-
-            if (count == null) {
-                count = 0;
-            }
-
-            mDepthOutputFormats.put(config.getFormat(), count + 1);
+            mDepthOutputFormats.put(config.getFormat(),
+                    mDepthOutputFormats.get(config.getFormat()) + 1);
         }
 
-        if (!mOutputFormats.containsKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)) {
+        if (mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) {
             throw new AssertionError(
                     "At least one stream configuration for IMPLEMENTATION_DEFINED must exist");
         }
@@ -241,7 +253,7 @@
      * @return a non-empty array of sizes, or {@code null} if the format was not available.
      */
     public Size[] getInputSizes(final int format) {
-        return getPublicFormatSizes(format, /*output*/false);
+        return getPublicFormatSizes(format, /*output*/false, /*highRes*/false);
     }
 
     /**
@@ -274,9 +286,9 @@
         int internalFormat = imageFormatToInternal(format);
         int dataspace = imageFormatToDataspace(format);
         if (dataspace == HAL_DATASPACE_DEPTH) {
-            return mDepthOutputFormats.containsKey(internalFormat);
+            return mDepthOutputFormats.indexOfKey(internalFormat) >= 0;
         } else {
-            return getFormatsMap(/*output*/true).containsKey(internalFormat);
+            return getFormatsMap(/*output*/true).indexOfKey(internalFormat) >= 0;
         }
     }
 
@@ -378,27 +390,24 @@
     public boolean isOutputSupportedFor(Surface surface) {
         checkNotNull(surface, "surface must not be null");
 
-        Size surfaceSize;
-        int surfaceFormat = -1;
-        try {
-            surfaceSize = LegacyCameraDevice.getSurfaceSize(surface);
-            surfaceFormat = LegacyCameraDevice.detectSurfaceType(surface);
-        } catch(BufferQueueAbandonedException e) {
-            throw new IllegalArgumentException("Abandoned surface", e);
-        }
+        Size surfaceSize = SurfaceUtils.getSurfaceSize(surface);
+        int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
+        int surfaceDataspace = SurfaceUtils.getSurfaceDataspace(surface);
 
         // See if consumer is flexible.
-        boolean isFlexible = LegacyCameraDevice.isFlexibleConsumer(surface);
+        boolean isFlexible = SurfaceUtils.isFlexibleConsumer(surface);
 
         // Override RGB formats to IMPLEMENTATION_DEFINED, b/9487482
         if ((surfaceFormat >= LegacyMetadataMapper.HAL_PIXEL_FORMAT_RGBA_8888 &&
                         surfaceFormat <= LegacyMetadataMapper.HAL_PIXEL_FORMAT_BGRA_8888)) {
-            surfaceFormat = LegacyMetadataMapper.HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+            surfaceFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
         }
 
-        for (StreamConfiguration config : mConfigurations) {
+        StreamConfiguration[] configs =
+                surfaceDataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
+        for (StreamConfiguration config : configs) {
             if (config.getFormat() == surfaceFormat && config.isOutput()) {
-                // Mathing format, either need exact size match, or a flexible consumer
+                // Matching format, either need exact size match, or a flexible consumer
                 // and a size no bigger than MAX_DIMEN_FOR_ROUNDING
                 if (config.getSize().equals(surfaceSize)) {
                     return true;
@@ -414,12 +423,12 @@
     /**
      * Get a list of sizes compatible with {@code klass} to use as an output.
      *
-     * <p>Since some of the supported classes may support additional formats beyond
+     * <p>Some of the supported classes may support additional formats beyond
      * {@link ImageFormat#PRIVATE}; this function only returns
      * sizes for {@link ImageFormat#PRIVATE}. For example, {@link android.media.ImageReader}
      * supports {@link ImageFormat#YUV_420_888} and {@link ImageFormat#PRIVATE}, this method will
      * only return the sizes for {@link ImageFormat#PRIVATE} for {@link android.media.ImageReader}
-     * class .</p>
+     * class.</p>
      *
      * <p>If a well-defined format such as {@code NV21} is required, use
      * {@link #getOutputSizes(int)} instead.</p>
@@ -444,7 +453,7 @@
         }
 
         return getInternalFormatSizes(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
-                HAL_DATASPACE_UNKNOWN,/*output*/true);
+                HAL_DATASPACE_UNKNOWN,/*output*/true, /*highRes*/false);
     }
 
     /**
@@ -453,6 +462,14 @@
      * <p>The {@code format} should be a supported format (one of the formats returned by
      * {@link #getOutputFormats}).</p>
      *
+     * As of API level 23, the {@link #getHighResolutionOutputSizes} method can be used on devices
+     * that support the
+     * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}
+     * capability to get a list of high-resolution output sizes that cannot operate at the preferred
+     * 20fps rate. This means that for some supported formats, this method will return an empty
+     * list, if all the supported resolutions operate at below 20fps.  For devices that do not
+     * support the BURST_CAPTURE capability, all output resolutions are listed through this method.
+     *
      * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
      * @return
      *          an array of supported sizes,
@@ -463,36 +480,40 @@
      * @see #getOutputFormats
      */
     public Size[] getOutputSizes(int format) {
-        return getPublicFormatSizes(format, /*output*/true);
+        return getPublicFormatSizes(format, /*output*/true, /*highRes*/ false);
     }
 
     /**
      * Get a list of supported high speed video recording sizes.
-     *
-     * <p> When HIGH_SPEED_VIDEO is supported in
-     * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES available scene modes}, this
-     * method will list the supported high speed video size configurations. All the sizes listed
-     * will be a subset of the sizes reported by {@link #getOutputSizes} for processed non-stalling
-     * formats (typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12)</p>
-     *
-     * <p> To enable high speed video recording, application must set
-     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
-     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
-     * requests and select the video size from this method and
+     * <p>
+     * When {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO} is
+     * supported in {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}, this method will
+     * list the supported high speed video size configurations. All the sizes listed will be a
+     * subset of the sizes reported by {@link #getOutputSizes} for processed non-stalling formats
+     * (typically {@link ImageFormat#PRIVATE} {@link ImageFormat#YUV_420_888}, etc.)
+     * </p>
+     * <p>
+     * To enable high speed video recording, application must create a constrained create high speed
+     * capture session via {@link CameraDevice#createConstrainedHighSpeedCaptureSession}, and submit
+     * a CaptureRequest list created by {@link CameraDevice#createConstrainedHighSpeedRequestList}
+     * to this session. The application must select the video size from this method and
      * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} from
-     * {@link #getHighSpeedVideoFpsRangesFor} to configure the recording and preview streams and
-     * setup the recording requests. For example, if the application intends to do high speed
-     * recording, it can select the maximum size reported by this method to configure output
-     * streams. Note that for the use case of multiple output streams, application must select one
-     * unique size from this method to use. Otherwise a request error might occur. Once the size is
+     * {@link #getHighSpeedVideoFpsRangesFor} to configure the constrained high speed session and
+     * generate the high speed request list. For example, if the application intends to do high
+     * speed recording, it can select the maximum size reported by this method to create high speed
+     * capture session. Note that for the use case of multiple output streams, application must
+     * select one unique size from this method to use (e.g., preview and recording streams must have
+     * the same size). Otherwise, the high speed session creation will fail. Once the size is
      * selected, application can get the supported FPS ranges by
      * {@link #getHighSpeedVideoFpsRangesFor}, and use these FPS ranges to setup the recording
-     * requests.</p>
+     * request lists via {@link CameraDevice#createConstrainedHighSpeedRequestList}.
+     * </p>
      *
-     * @return
-     *          an array of supported high speed video recording sizes
-     *
+     * @return an array of supported high speed video recording sizes
      * @see #getHighSpeedVideoFpsRangesFor(Size)
+     * @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+     * @see CameraDevice#createConstrainedHighSpeedCaptureSession
+     * @see CameraDevice#createConstrainedHighSpeedRequestList
      */
     public Size[] getHighSpeedVideoSizes() {
         Set<Size> keySet = mHighSpeedVideoSizeMap.keySet();
@@ -501,26 +522,25 @@
 
     /**
      * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size.
-     *
-     * <p> See {@link #getHighSpeedVideoSizes} for how to enable high speed recording.</p>
-     *
-     * <p> For normal video recording use case, where some application will NOT set
-     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
-     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
-     * requests, the {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in
-     * this method must not be used to setup capture requests, or it will cause request error.</p>
+     * <p>
+     * See {@link #getHighSpeedVideoFpsRanges} for how to enable high speed recording.
+     * </p>
+     * <p>
+     * The {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in this method
+     * must not be used to setup capture requests that are submitted to unconstrained capture
+     * sessions, or it will result in {@link IllegalArgumentException IllegalArgumentExceptions}.
+     * </p>
+     * <p>
+     * See {@link #getHighSpeedVideoFpsRanges} for the characteristics of the returned FPS ranges.
+     * </p>
      *
      * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()}
-     * @return
-     *          An array of FPS range to use with
-     *          {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE TARGET_FPS_RANGE} when using
-     *          {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} scene
-     *          mode.
-     *          The upper bound of returned ranges is guaranteed to be larger or equal to 60.
-     *
+     * @return an array of supported high speed video recording FPS ranges The upper bound of
+     *         returned ranges is guaranteed to be greater than or equal to 120.
      * @throws IllegalArgumentException if input size does not exist in the return value of
-     *         getHighSpeedVideoSizes
+     *             getHighSpeedVideoSizes
      * @see #getHighSpeedVideoSizes()
+     * @see #getHighSpeedVideoFpsRanges()
      */
     public Range<Integer>[] getHighSpeedVideoFpsRangesFor(Size size) {
         Integer fpsRangeCount = mHighSpeedVideoSizeMap.get(size);
@@ -542,34 +562,46 @@
 
     /**
      * Get a list of supported high speed video recording FPS ranges.
-     *
-     * <p> When HIGH_SPEED_VIDEO is supported in
-     * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES available scene modes}, this
-     * method will list the supported high speed video FPS range configurations. Application can
-     * then use {@link #getHighSpeedVideoSizesFor} to query available sizes for one of returned
-     * FPS range.</p>
-     *
-     * <p> To enable high speed video recording, application must set
-     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
-     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
-     * requests and select the video size from {@link #getHighSpeedVideoSizesFor} and
+     * <p>
+     * When {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO} is
+     * supported in {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}, this method will
+     * list the supported high speed video FPS range configurations. Application can then use
+     * {@link #getHighSpeedVideoSizesFor} to query available sizes for one of returned FPS range.
+     * </p>
+     * <p>
+     * To enable high speed video recording, application must create a constrained create high speed
+     * capture session via {@link CameraDevice#createConstrainedHighSpeedCaptureSession}, and submit
+     * a CaptureRequest list created by {@link CameraDevice#createConstrainedHighSpeedRequestList}
+     * to this session. The application must select the video size from this method and
      * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} from
-     * this method to configure the recording and preview streams and setup the recording requests.
-     * For example, if the application intends to do high speed recording, it can select one FPS
-     * range reported by this method, query the video sizes corresponding to this FPS range  by
-     * {@link #getHighSpeedVideoSizesFor} and select one of reported sizes to configure output
-     * streams. Note that for the use case of multiple output streams, application must select one
-     * unique size from {@link #getHighSpeedVideoSizesFor}, and use it for all output streams.
-     * Otherwise a request error might occur when attempting to enable
-     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}.
-     * Once the stream is configured, application can set the FPS range in the recording requests.
+     * {@link #getHighSpeedVideoFpsRangesFor} to configure the constrained high speed session and
+     * generate the high speed request list. For example, if the application intends to do high
+     * speed recording, it can select one FPS range reported by this method, query the video sizes
+     * corresponding to this FPS range by {@link #getHighSpeedVideoSizesFor} and use one of reported
+     * sizes to create a high speed capture session. Note that for the use case of multiple output
+     * streams, application must select one unique size from this method to use (e.g., preview and
+     * recording streams must have the same size). Otherwise, the high speed session creation will
+     * fail. Once the high speed capture session is created, the application can set the FPS range
+     * in the recording request lists via
+     * {@link CameraDevice#createConstrainedHighSpeedRequestList}.
+     * </p>
+     * <p>
+     * The FPS ranges reported by this method will have below characteristics:
+     * <li>The fpsMin and fpsMax will be a multiple 30fps.</li>
+     * <li>The fpsMin will be no less than 30fps, the fpsMax will be no less than 120fps.</li>
+     * <li>At least one range will be a fixed FPS range where fpsMin == fpsMax.</li>
+     * <li>For each fixed FPS range, there will be one corresponding variable FPS range [30,
+     * fps_max]. These kinds of FPS ranges are suitable for preview-only use cases where the
+     * application doesn't want the camera device always produce higher frame rate than the display
+     * refresh rate.</li>
      * </p>
      *
-     * @return
-     *          an array of supported high speed video recording FPS ranges
-     *          The upper bound of returned ranges is guaranteed to be larger or equal to 60.
-     *
+     * @return an array of supported high speed video recording FPS ranges The upper bound of
+     *         returned ranges is guaranteed to be larger or equal to 120.
      * @see #getHighSpeedVideoSizesFor
+     * @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+     * @see CameraDevice#createConstrainedHighSpeedCaptureSession
+     * @see CameraDevice#createConstrainedHighSpeedRequestList
      */
     @SuppressWarnings("unchecked")
     public Range<Integer>[] getHighSpeedVideoFpsRanges() {
@@ -578,21 +610,13 @@
     }
 
     /**
-     * Get the supported video sizes for input FPS range.
+     * Get the supported video sizes for an input high speed FPS range.
      *
-     * <p> See {@link #getHighSpeedVideoFpsRanges} for how to enable high speed recording.</p>
-     *
-     * <p> For normal video recording use case, where the application will NOT set
-     * {@link CaptureRequest#CONTROL_SCENE_MODE} to
-     * {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} in capture
-     * requests, the {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS ranges} reported in
-     * this method must not be used to setup capture requests, or it will cause request error.</p>
+     * <p> See {@link #getHighSpeedVideoSizes} for how to enable high speed recording.</p>
      *
      * @param fpsRange one of the FPS range returned by {@link #getHighSpeedVideoFpsRanges()}
-     * @return
-     *          An array of video sizes to configure output stream when using
-     *          {@link CaptureRequest#CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO} scene
-     *          mode.
+     * @return An array of video sizes to create high speed capture sessions for high speed streaming
+     *         use cases.
      *
      * @throws IllegalArgumentException if input FPS range does not exist in the return value of
      *         getHighSpeedVideoFpsRanges
@@ -616,6 +640,32 @@
     }
 
     /**
+     * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE
+     * rate.
+     *
+     * <p>This includes all output sizes that cannot meet the 20 fps frame rate requirements for the
+     * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}
+     * capability.  This does not include the stall duration, so for example, a JPEG or RAW16 output
+     * resolution with a large stall duration but a minimum frame duration that's above 20 fps will
+     * still be listed in the regular {@link #getOutputSizes} list. All the sizes on this list are
+     * still guaranteed to operate at a rate of at least 10 fps, not including stall duration.</p>
+     *
+     * <p>For a device that does not support the BURST_CAPTURE capability, this list will be
+     * {@code null}, since resolutions in the {@link #getOutputSizes} list are already not
+     * guaranteed to meet &gt;= 20 fps rate requirements. For a device that does support the
+     * BURST_CAPTURE capability, this list may be empty, if all supported resolutions meet the 20
+     * fps requirement.</p>
+     *
+     * @return an array of supported slower high-resolution sizes, or {@code null} if the
+     *         BURST_CAPTURE capability is not supported
+     */
+    public Size[] getHighResolutionOutputSizes(int format) {
+        if (!mListHighResolution) return null;
+
+        return getPublicFormatSizes(format, /*output*/true, /*highRes*/ true);
+    }
+
+    /**
      * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
      * for the format/size combination (in nanoseconds).
      *
@@ -867,6 +917,7 @@
             return Arrays.equals(mConfigurations, other.mConfigurations) &&
                     Arrays.equals(mMinFrameDurations, other.mMinFrameDurations) &&
                     Arrays.equals(mStallDurations, other.mStallDurations) &&
+                    Arrays.equals(mDepthConfigurations, other.mDepthConfigurations) &&
                     Arrays.equals(mHighSpeedVideoConfigurations,
                             other.mHighSpeedVideoConfigurations);
         }
@@ -879,18 +930,31 @@
     @Override
     public int hashCode() {
         // XX: do we care about order?
-        return HashCodeHelpers.hashCode(
+        return HashCodeHelpers.hashCodeGeneric(
                 mConfigurations, mMinFrameDurations,
-                mStallDurations, mHighSpeedVideoConfigurations);
+                mStallDurations,
+                mDepthConfigurations, mHighSpeedVideoConfigurations);
     }
 
     // Check that the argument is supported by #getOutputFormats or #getInputFormats
     private int checkArgumentFormatSupported(int format, boolean output) {
         checkArgumentFormat(format);
 
-        int[] formats = output ? getOutputFormats() : getInputFormats();
-        for (int i = 0; i < formats.length; ++i) {
-            if (format == formats[i]) {
+        int internalFormat = imageFormatToInternal(format);
+        int internalDataspace = imageFormatToDataspace(format);
+
+        if (output) {
+            if (internalDataspace == HAL_DATASPACE_DEPTH) {
+                if (mDepthOutputFormats.indexOfKey(internalFormat) >= 0) {
+                    return format;
+                }
+            } else {
+                if (mAllOutputFormats.indexOfKey(internalFormat) >= 0) {
+                    return format;
+                }
+            }
+        } else {
+            if (mInputFormats.indexOfKey(internalFormat) >= 0) {
                 return format;
             }
         }
@@ -1175,7 +1239,7 @@
         return formats;
     }
 
-    private Size[] getPublicFormatSizes(int format, boolean output) {
+    private Size[] getPublicFormatSizes(int format, boolean output, boolean highRes) {
         try {
             checkArgumentFormatSupported(format, output);
         } catch (IllegalArgumentException e) {
@@ -1185,36 +1249,57 @@
         int internalFormat = imageFormatToInternal(format);
         int dataspace = imageFormatToDataspace(format);
 
-        return getInternalFormatSizes(internalFormat, dataspace, output);
+        return getInternalFormatSizes(internalFormat, dataspace, output, highRes);
     }
 
-    private Size[] getInternalFormatSizes(int format, int dataspace, boolean output) {
+    private Size[] getInternalFormatSizes(int format, int dataspace,
+            boolean output, boolean highRes) {
+        SparseIntArray formatsMap =
+                !output ? mInputFormats :
+                dataspace == HAL_DATASPACE_DEPTH ? mDepthOutputFormats :
+                highRes ? mHighResOutputFormats :
+                mOutputFormats;
 
-        HashMap<Integer, Integer> formatsMap =
-                (dataspace == HAL_DATASPACE_DEPTH) ? mDepthOutputFormats : getFormatsMap(output);
-
-        Integer sizesCount = formatsMap.get(format);
-        if (sizesCount == null) {
+        int sizesCount = formatsMap.get(format);
+        if ( ((!output || dataspace == HAL_DATASPACE_DEPTH) && sizesCount == 0) ||
+                (output && dataspace != HAL_DATASPACE_DEPTH && mAllOutputFormats.get(format) == 0)) {
+            // Only throw if this is really not supported at all
             throw new IllegalArgumentException("format not available");
         }
 
-        int len = sizesCount;
-        Size[] sizes = new Size[len];
+        Size[] sizes = new Size[sizesCount];
         int sizeIndex = 0;
 
         StreamConfiguration[] configurations =
                 (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
 
-
         for (StreamConfiguration config : configurations) {
-            if (config.getFormat() == format && config.isOutput() == output) {
+            int fmt = config.getFormat();
+            if (fmt == format && config.isOutput() == output) {
+                if (output) {
+                    // Filter slow high-res output formats; include for
+                    // highRes, remove for !highRes
+                    long duration = 0;
+                    for (int i = 0; i < mMinFrameDurations.length; i++) {
+                        StreamConfigurationDuration d = mMinFrameDurations[i];
+                        if (d.getFormat() == fmt &&
+                                d.getWidth() == config.getSize().getWidth() &&
+                                d.getHeight() == config.getSize().getHeight()) {
+                            duration = d.getDuration();
+                            break;
+                        }
+                    }
+                    if (highRes != (duration > DURATION_20FPS_NS)) {
+                        continue;
+                    }
+                }
                 sizes[sizeIndex++] = config.getSize();
             }
         }
 
-        if (sizeIndex != len) {
+        if (sizeIndex != sizesCount) {
             throw new AssertionError(
-                    "Too few sizes (expected " + len + ", actual " + sizeIndex + ")");
+                    "Too few sizes (expected " + sizesCount + ", actual " + sizeIndex + ")");
         }
 
         return sizes;
@@ -1226,14 +1311,16 @@
 
         int i = 0;
 
-        for (int format : getFormatsMap(output).keySet()) {
+        SparseIntArray map = getFormatsMap(output);
+        for (int j = 0; j < map.size(); j++) {
+            int format = map.keyAt(j);
             if (format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
                 formats[i++] = imageFormatToPublic(format);
             }
         }
         if (output) {
-            for (int format : mDepthOutputFormats.keySet()) {
-                formats[i++] = depthFormatToPublic(format);
+            for (int j = 0; j < mDepthOutputFormats.size(); j++) {
+                formats[i++] = depthFormatToPublic(mDepthOutputFormats.keyAt(j));
             }
         }
         if (formats.length != i) {
@@ -1244,14 +1331,14 @@
     }
 
     /** Get the format -> size count map for either output or input formats */
-    private HashMap<Integer, Integer> getFormatsMap(boolean output) {
-        return output ? mOutputFormats : mInputFormats;
+    private SparseIntArray getFormatsMap(boolean output) {
+        return output ? mAllOutputFormats : mInputFormats;
     }
 
     private long getInternalFormatDuration(int format, int dataspace, Size size, int duration) {
         // assume format is already checked, since its internal
 
-        if (!arrayContains(getInternalFormatSizes(format, dataspace, /*output*/true), size)) {
+        if (!isSupportedInternalConfiguration(format, dataspace, size)) {
             throw new IllegalArgumentException("size was not supported");
         }
 
@@ -1289,10 +1376,9 @@
 
     /** Count the number of publicly-visible output formats */
     private int getPublicFormatCount(boolean output) {
-        HashMap<Integer, Integer> formatsMap = getFormatsMap(output);
-
+        SparseIntArray formatsMap = getFormatsMap(output);
         int size = formatsMap.size();
-        if (formatsMap.containsKey(HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
+        if (formatsMap.indexOfKey(HAL_PIXEL_FORMAT_RAW_OPAQUE) >= 0) {
             size -= 1;
         }
         if (output) {
@@ -1316,6 +1402,21 @@
         return false;
     }
 
+    private boolean isSupportedInternalConfiguration(int format, int dataspace,
+            Size size) {
+        StreamConfiguration[] configurations =
+                (dataspace == HAL_DATASPACE_DEPTH) ? mDepthConfigurations : mConfigurations;
+
+        for (int i = 0; i < configurations.length; i++) {
+            if (configurations[i].getFormat() == format &&
+                    configurations[i].getSize().equals(size)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Return this {@link StreamConfigurationMap} as a string representation.
      *
@@ -1351,6 +1452,8 @@
         StringBuilder sb = new StringBuilder("StreamConfiguration(");
         appendOutputsString(sb);
         sb.append(", ");
+        appendHighResOutputsString(sb);
+        sb.append(", ");
         appendInputsString(sb);
         sb.append(", ");
         appendValidOutputFormatsForInputString(sb);
@@ -1381,6 +1484,27 @@
         sb.append(")");
     }
 
+    private void appendHighResOutputsString(StringBuilder sb) {
+        sb.append("HighResolutionOutputs(");
+        int[] formats = getOutputFormats();
+        for (int format : formats) {
+            Size[] sizes = getHighResolutionOutputSizes(format);
+            if (sizes == null) continue;
+            for (Size size : sizes) {
+                long minFrameDuration = getOutputMinFrameDuration(format, size);
+                long stallDuration = getOutputStallDuration(format, size);
+                sb.append(String.format("[w:%d, h:%d, format:%s(%d), min_duration:%d, " +
+                        "stall:%d], ", size.getWidth(), size.getHeight(), formatToString(format),
+                        format, minFrameDuration, stallDuration));
+            }
+        }
+        // Remove the pending ", "
+        if (sb.charAt(sb.length() - 1) == ' ') {
+            sb.delete(sb.length() - 2, sb.length());
+        }
+        sb.append(")");
+    }
+
     private void appendInputsString(StringBuilder sb) {
         sb.append("Inputs(");
         int[] formats = getInputFormats();
@@ -1479,15 +1603,21 @@
     }
 
     // from system/core/include/system/graphics.h
+    private static final int HAL_PIXEL_FORMAT_RAW16 = 0x20;
     private static final int HAL_PIXEL_FORMAT_BLOB = 0x21;
     private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
+    private static final int HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23;
     private static final int HAL_PIXEL_FORMAT_RAW_OPAQUE = 0x24;
+    private static final int HAL_PIXEL_FORMAT_RAW10 = 0x25;
+    private static final int HAL_PIXEL_FORMAT_RAW12 = 0x26;
     private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
 
+
     private static final int HAL_DATASPACE_UNKNOWN = 0x0;
     private static final int HAL_DATASPACE_JFIF = 0x101;
     private static final int HAL_DATASPACE_DEPTH = 0x1000;
 
+    private static final long DURATION_20FPS_NS = 50000000L;
     /**
      * @see #getDurations(int, int)
      */
@@ -1505,15 +1635,20 @@
     private final HighSpeedVideoConfiguration[] mHighSpeedVideoConfigurations;
     private final ReprocessFormatsMap mInputOutputFormatsMap;
 
-    /** ImageFormat -> num output sizes mapping */
-    private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mOutputFormats =
-            new HashMap<Integer, Integer>();
-    /** ImageFormat -> num input sizes mapping */
-    private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mInputFormats =
-            new HashMap<Integer, Integer>();
-    /** ImageFormat -> num depth output sizes mapping */
-    private final HashMap</*ImageFormat*/Integer, /*Count*/Integer> mDepthOutputFormats =
-            new HashMap<Integer, Integer>();
+    private final boolean mListHighResolution;
+
+    /** internal format -> num output sizes mapping, not including slow high-res sizes, for
+     * non-depth dataspaces */
+    private final SparseIntArray mOutputFormats = new SparseIntArray();
+    /** internal format -> num output sizes mapping for slow high-res sizes, for non-depth
+     * dataspaces */
+    private final SparseIntArray mHighResOutputFormats = new SparseIntArray();
+    /** internal format -> num output sizes mapping for all non-depth dataspaces */
+    private final SparseIntArray mAllOutputFormats = new SparseIntArray();
+    /** internal format -> num input sizes mapping, for input reprocessing formats */
+    private final SparseIntArray mInputFormats = new SparseIntArray();
+    /** internal format -> num depth output sizes mapping, for HAL_DATASPACE_DEPTH */
+    private final SparseIntArray mDepthOutputFormats = new SparseIntArray();
     /** High speed video Size -> FPS range count mapping*/
     private final HashMap</*HighSpeedVideoSize*/Size, /*Count*/Integer> mHighSpeedVideoSizeMap =
             new HashMap<Size, Integer>();
@@ -1522,4 +1657,3 @@
             mHighSpeedVideoFpsRangeMap = new HashMap<Range<Integer>, Integer>();
 
 }
-
diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java
index 398a7e9..2d7bbaa 100644
--- a/core/java/android/hardware/camera2/params/TonemapCurve.java
+++ b/core/java/android/hardware/camera2/params/TonemapCurve.java
@@ -277,7 +277,7 @@
             return mHashCode;
         }
 
-        mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue);
+        mHashCode = HashCodeHelpers.hashCodeGeneric(mRed, mGreen, mBlue);
         mHashCalculated = true;
 
         return mHashCode;
diff --git a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
index 7b4aa09..731da8b 100644
--- a/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
+++ b/core/java/android/hardware/camera2/utils/HashCodeHelpers.java
@@ -30,7 +30,7 @@
      *
      * @return the numeric hash code
      */
-    public static int hashCode(int[] array) {
+    public static int hashCode(int... array) {
         if (array == null) {
             return 0;
         }
@@ -60,7 +60,7 @@
      *
      * @return the numeric hash code
      */
-    public static int hashCode(float[] array) {
+    public static int hashCode(float... array) {
         if (array == null) {
             return 0;
         }
@@ -83,7 +83,7 @@
      *
      * @return the numeric hash code
      */
-    public static <T> int hashCode(T[] array) {
+    public static <T> int hashCodeGeneric(T... array) {
         if (array == null) {
             return 0;
         }
@@ -97,56 +97,4 @@
         return h;
     }
 
-    public static <T> int hashCode(T a) {
-        return (a == null) ? 0 : a.hashCode();
-    }
-
-    public static <T> int hashCode(T a, T b) {
-        int h = hashCode(a);
-
-        int x = (b == null) ? 0 : b.hashCode();
-        h = ((h << 5) - h) ^ x; // (h * 31) XOR x
-
-        return h;
-    }
-
-    public static <T> int hashCode(T a, T b, T c) {
-        int h = hashCode(a, b);
-
-        int x = (c == null) ? 0 : c.hashCode();
-        h = ((h << 5) - h) ^ x; // (h * 31) XOR x
-
-        return h;
-    }
-
-    public static <T> int hashCode(T a, T b, T c, T d) {
-        int h = hashCode(a, b, c);
-
-        int x = (d == null) ? 0 : d.hashCode();
-        h = ((h << 5) - h) ^ x; // (h * 31) XOR x
-
-        return h;
-    }
-
-    public static int hashCode(int x) {
-        return hashCode(new int[] { x } );
-    }
-
-    public static int hashCode(int x, int y) {
-        return hashCode(new int[] { x, y } );
-    }
-
-    public static int hashCode(int x, int y, int z) {
-        return hashCode(new int[] { x, y, z } );
-    }
-
-    public static int hashCode(int x, int y, int z, int w) {
-        return hashCode(new int[] { x, y, z, w } );
-    }
-
-    public static int hashCode(int x, int y, int z, int w, int t) {
-        return hashCode(new int[] { x, y, z, w, t } );
-    }
-
-
 }
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
index 40005a5..064b21a 100644
--- a/core/java/android/hardware/camera2/utils/SurfaceUtils.java
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -79,4 +79,30 @@
             throw new IllegalArgumentException("Surface was abandoned", e);
         }
     }
+
+    /**
+     * Get the Surface dataspace.
+     *
+     * @param surface The surface to be queried for dataspace.
+     * @return dataspace of the surface.
+     *
+     * @throws IllegalArgumentException if the surface is already abandoned.
+     */
+    public static int getSurfaceDataspace(Surface surface) {
+        try {
+            return LegacyCameraDevice.detectSurfaceDataspace(surface);
+        } catch (BufferQueueAbandonedException e) {
+            throw new IllegalArgumentException("Surface was abandoned", e);
+        }
+    }
+
+    /**
+     * Return true is the consumer is one of the consumers that can accept
+     * producer overrides of the default dimensions and format.
+     *
+     */
+    public static boolean isFlexibleConsumer(Surface output) {
+        return LegacyCameraDevice.isFlexibleConsumer(output);
+    }
+
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b9f7365..80476ea 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2110,6 +2110,8 @@
          * can automatically log in to a captive portal without user intervention.
          *
          * @param network The {@link Network} of the network that is being evaluated.
+         *
+         * @hide
          */
         public void onPreCheck(Network network) {}
 
@@ -2379,6 +2381,14 @@
      * Status of the request can be followed by listening to the various
      * callbacks described in {@link NetworkCallback}.  The {@link Network}
      * can be used to direct traffic to the network.
+     * <p>It is presently unsupported to request a network with mutable
+     * {@link NetworkCapabilities} such as
+     * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+     * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
+     * as these {@code NetworkCapabilities} represent states that a particular
+     * network may never attain, and whether a network will attain these states
+     * is unknown prior to bringing up the network so the framework does not
+     * know how to go about satisfing a request with these capabilities.
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
      *
@@ -2386,6 +2396,8 @@
      * @param networkCallback The {@link NetworkCallback} to be utilized for this
      *                        request.  Note the callback must not be shared - they
      *                        uniquely specify this request.
+     * @throws IllegalArgumentException if {@code request} specifies any mutable
+     *         {@code NetworkCapabilities}.
      */
     public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback) {
         sendRequestForNetwork(request.networkCapabilities, networkCallback, 0,
@@ -2467,12 +2479,22 @@
      * <p>
      * The request may be released normally by calling
      * {@link #releaseNetworkRequest(android.app.PendingIntent)}.
+     * <p>It is presently unsupported to request a network with either
+     * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+     * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
+     * as these {@code NetworkCapabilities} represent states that a particular
+     * network may never attain, and whether a network will attain these states
+     * is unknown prior to bringing up the network so the framework does not
+     * know how to go about satisfing a request with these capabilities.
      * <p>This method requires the caller to hold the permission
      * {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
      * @param request {@link NetworkRequest} describing this request.
      * @param operation Action to perform when the network is available (corresponds
      *                  to the {@link NetworkCallback#onAvailable} call.  Typically
      *                  comes from {@link PendingIntent#getBroadcast}. Cannot be null.
+     * @throws IllegalArgumentException if {@code request} contains either
+     *         {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+     *         {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}.
      */
     public void requestNetwork(NetworkRequest request, PendingIntent operation) {
         checkPendingIntent(operation);
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index cf747cf..658051c 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -173,12 +173,17 @@
      * Indicates that connectivity on this network was successfully validated. For example, for a
      * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully
      * detected.
-     * @hide
      */
     public static final int NET_CAPABILITY_VALIDATED      = 16;
 
+    /**
+     * Indicates that this network was found to have a captive portal in place last time it was
+     * probed.
+     */
+    public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_VALIDATED;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL;
 
     /**
      * Adds the given capability to this {@code NetworkCapability} instance.
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 87e8c5e..97b85e2 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1469,13 +1469,30 @@
      *         </tr>
      *         <tr>
      *             <td>art.gc.gc-count-rate-histogram</td>
-     *             <td>The histogram of the number of garbage collection runs per 10 seconds.</td>
+     *             <td>Every 10 seconds, the gc-count-rate is computed as the number of garbage
+     *                 collection runs that have occurred over the last 10
+     *                 seconds. art.gc.gc-count-rate-histogram is a histogram of the gc-count-rate
+     *                 samples taken since the process began. The histogram can be used to identify
+     *                 instances of high rates of garbage collection runs. For example, a histogram
+     *                 of "0:34503,1:45350,2:11281,3:8088,4:43,5:8" shows that most of the time
+     *                 there are between 0 and 2 garbage collection runs every 10 seconds, but there
+     *                 were 8 distinct 10-second intervals in which 5 garbage collection runs
+     *                 occurred.</td>
      *             <td>{@code 0:34503,1:45350,2:11281,3:8088,4:43,5:8}</td>
      *             <td>23</td>
      *         </tr>
      *         <tr>
      *             <td>art.gc.blocking-gc-count-rate-histogram</td>
-     *             <td>The histogram of the number of garbage collection runs per 10 seconds.</td>
+     *             <td>Every 10 seconds, the blocking-gc-count-rate is computed as the number of
+     *                 blocking garbage collection runs that have occurred over the last 10
+     *                 seconds. art.gc.blocking-gc-count-rate-histogram is a histogram of the
+     *                 blocking-gc-count-rate samples taken since the process began. The histogram
+     *                 can be used to identify instances of high rates of blocking garbage
+     *                 collection runs. For example, a histogram of "0:99269,1:1,2:1" shows that
+     *                 most of the time there are zero blocking garbage collection runs every 10
+     *                 seconds, but there was one 10-second interval in which one blocking garbage
+     *                 collection run occurred, and there was one interval in which two blocking
+     *                 garbage collection runs occurred.</td>
      *             <td>{@code 0:99269,1:1,2:1}</td>
      *             <td>23</td>
      *         </tr>
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 1cc2d33..f10b982 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1919,9 +1919,9 @@
         for (int i = 0; i < numViolations; ++i) {
             if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call.  i=" + i);
             ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
-            if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 10000) {
+            if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
                 String front = info.crashInfo.stackTrace.substring(256);
-                // 10000 characters is way too large for this to be any sane kind of
+                // 30000 characters is way too large for this to be any sane kind of
                 // strict mode collection of stacks.  We've had a problem where we leave
                 // strict mode violations associated with the thread, and it keeps tacking
                 // more and more stacks on to the violations.  Looks like we're in this casse,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 56cd1a7..9b5fbfa 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6685,6 +6685,17 @@
            "wifi_mobile_data_transition_wakelock_timeout_ms";
 
        /**
+        * This setting controls whether WiFi configurations created by a Device Owner app
+        * should be locked down (that is, be editable or removable only by the Device Owner App,
+        * not even by Settings app).
+        * This setting takes integer values. Non-zero values mean DO created configurations
+        * are locked down. Value of zero means they are not. Default value in the absence of
+        * actual value to this setting is 0.
+        */
+       public static final String WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN =
+               "wifi_device_owner_configs_lockdown";
+
+       /**
         * The operational wifi frequency band
         * Set to one of {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
         * {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ} or
diff --git a/core/java/android/security/keymaster/KeymasterArguments.java b/core/java/android/security/keymaster/KeymasterArguments.java
index 82f65c7..363376c 100644
--- a/core/java/android/security/keymaster/KeymasterArguments.java
+++ b/core/java/android/security/keymaster/KeymasterArguments.java
@@ -85,6 +85,12 @@
         mArguments.add(new KeymasterDateArgument(tag, value));
     }
 
+    public void addDateIfNotNull(int tag, Date value) {
+        if (value != null) {
+            mArguments.add(new KeymasterDateArgument(tag, value));
+        }
+    }
+
     private KeymasterArgument getArgumentByTag(int tag) {
         for (KeymasterArgument arg : mArguments) {
             if (arg.tag == tag) {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 39dd29b..f9e216a 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1146,20 +1146,7 @@
         mContentFrame.requestApplyInsets();
     }
 
-    /** @hide */
-    public void onHandleAssist(Bundle assistBundle) {
-    }
-
     public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) {
-        if (data != null) {
-            Bundle assistContext = data.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
-            if (assistContext != null) {
-                assistContext.putParcelable(AssistStructure.ASSIST_KEY, structure);
-                assistContext.putParcelable(AssistContent.ASSIST_KEY, content);
-                data.putBundle(Intent.EXTRA_ASSIST_CONTEXT, assistContext);
-            }
-        }
-        onHandleAssist(data);
     }
 
     public void onHandleScreenshot(Bitmap screenshot) {
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 13a959e..47d5c79 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -16,6 +16,7 @@
 
 package android.text.format;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.NetworkUtils;
@@ -52,7 +53,10 @@
      * @param sizeBytes size value to be formatted, in bytes
      * @return formatted string with the number
      */
-    public static String formatFileSize(Context context, long sizeBytes) {
+    public static String formatFileSize(@Nullable Context context, long sizeBytes) {
+        if (context == null) {
+            return "";
+        }
         final BytesResult res = formatBytes(context.getResources(), sizeBytes, 0);
         return context.getString(com.android.internal.R.string.fileSizeSuffix,
                 res.value, res.units);
@@ -62,7 +66,10 @@
      * Like {@link #formatFileSize}, but trying to generate shorter numbers
      * (showing fewer digits of precision).
      */
-    public static String formatShortFileSize(Context context, long sizeBytes) {
+    public static String formatShortFileSize(@Nullable Context context, long sizeBytes) {
+        if (context == null) {
+            return "";
+        }
         final BytesResult res = formatBytes(context.getResources(), sizeBytes, FLAG_SHORTER);
         return context.getString(com.android.internal.R.string.fileSizeSuffix,
                 res.value, res.units);
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 8b74a1e..585fc4e 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -504,13 +504,20 @@
         private final boolean mIsForcedVisibility;
         private final View mView;
         private final int mFinalVisibility;
+        private final ViewGroup mParent;
 
+        private boolean mEnded;
         boolean mCanceled = false;
 
         public DisappearListener(View view, int finalVisibility, boolean isForcedVisibility) {
             this.mView = view;
             this.mIsForcedVisibility = isForcedVisibility;
             this.mFinalVisibility = finalVisibility;
+            this.mParent = (ViewGroup) view.getParent();
+            if (!isForcedVisibility && mParent != null) {
+                // Prevent a layout from including mView in its calculation.
+                mParent.suppressLayout(true);
+            }
         }
 
         @Override
@@ -552,13 +559,39 @@
             hideViewWhenNotCanceled();
         }
 
+        @Override
+        public void onTransitionPause(Transition transition) {
+            if (mParent != null && !mIsForcedVisibility) {
+                mParent.suppressLayout(false);
+            }
+        }
+
+        @Override
+        public void onTransitionResume(Transition transition) {
+            if (mParent != null && !mIsForcedVisibility) {
+                mParent.suppressLayout(true);
+            }
+        }
+
         private void hideViewWhenNotCanceled() {
-            if (!mCanceled) {
-                if (mIsForcedVisibility) {
-                    mView.setTransitionAlpha(0);
-                } else {
-                    mView.setVisibility(mFinalVisibility);
+            if (!mEnded) {
+                if (!mCanceled) {
+                    if (mIsForcedVisibility) {
+                        mView.setTransitionAlpha(0);
+                    } else {
+                        // Recreate the parent's display list in case it includes mView.
+                        mView.setTransitionVisibility(mFinalVisibility);
+                        if (mParent != null) {
+                            mParent.invalidate();
+                        }
+                    }
                 }
+                if (!mIsForcedVisibility && mParent != null) {
+                    // Layout is allowed now that the View is in its final state
+                    mParent.suppressLayout(false);
+                }
+                // Do this only once
+                mEnded = true;
             }
         }
     }
diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java
index 211d01a..5524506 100644
--- a/core/java/android/util/Range.java
+++ b/core/java/android/util/Range.java
@@ -350,7 +350,7 @@
      */
     @Override
     public int hashCode() {
-        return HashCodeHelpers.hashCode(mLower, mUpper);
+        return HashCodeHelpers.hashCodeGeneric(mLower, mUpper);
     }
 
     private final T mLower;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 4394cd8..6026d04 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1399,6 +1399,7 @@
     private static native int nativeGetButtonState(long nativePtr);
     private static native void nativeSetButtonState(long nativePtr, int buttonState);
     private static native int nativeGetActionButton(long nativePtr);
+    private static native void nativeSetActionButton(long nativePtr, int actionButton);
     private static native void nativeOffsetLocation(long nativePtr, float deltaX, float deltaY);
     private static native float nativeGetXOffset(long nativePtr);
     private static native float nativeGetYOffset(long nativePtr);
@@ -2284,6 +2285,16 @@
     }
 
     /**
+     * Sets the action button for the event.
+     *
+     * @see #getActionButton()
+     * @hide
+     */
+    public final void setActionButton(int button) {
+        nativeSetActionButton(mNativePtr, button);
+    }
+
+    /**
      * Returns the original raw X coordinate of this event.  For touch
      * events on the screen, this is the original location of the event
      * on the screen, before it had been adjusted for the containing window
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 4074529..5970c3f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -453,6 +453,19 @@
         }
     }
 
+    /**
+     * Sets the security of the surface.  Setting the flag is equivalent to creating the
+     * Surface with the {@link #SECURE} flag.
+     */
+    public void setSecure(boolean isSecure) {
+        checkNotReleased();
+        if (isSecure) {
+            nativeSetFlags(mNativeObject, SECURE, SECURE);
+        } else {
+            nativeSetFlags(mNativeObject, 0, SECURE);
+        }
+    }
+
     /*
      * set display parameters.
      * needs to be inside open/closeTransaction block
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fd3ee4f..92dae2e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6032,7 +6032,7 @@
     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
         if (provider != null) {
-            return provider.createAccessibilityNodeInfo(View.NO_ID);
+            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
         } else {
             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
             onInitializeAccessibilityNodeInfo(info);
@@ -6326,6 +6326,10 @@
      * @hide
      */
     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+        if (mAttachInfo == null) {
+            return;
+        }
+
         Rect bounds = mAttachInfo.mTmpInvalRect;
 
         getDrawingRect(bounds);
@@ -8774,7 +8778,7 @@
      * @hide
      */
     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
-        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
+        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
             return;
         }
         if (mSendViewStateChangedAccessibilityEvent == null) {
@@ -8796,7 +8800,7 @@
      * @hide
      */
     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
-        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
+        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
             return;
         }
         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index d06cd83..3572f1e 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -150,7 +150,7 @@
      * @param size The size, in pixels, of the text.
      * @param fgColor The foreground color, packed as 0xAARRGGBB.
      * @param bgColor The background color, packed as 0xAARRGGBB.
-     * @param style Style flags, as defined by {@link android.app.AssistStructure.ViewNode}.
+     * @param style Style flags, as defined by {@link android.app.assist.AssistStructure.ViewNode}.
      */
     public abstract void setTextStyle(float size, int fgColor, int bgColor, int style);
 
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index ab793e0..87706ef 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -1115,7 +1115,7 @@
         record.mParcelableData = parcel.readParcelable(null);
         parcel.readList(record.mText, null);
         record.mSourceWindowId = parcel.readInt();
-        record.mSourceNodeId = parcel.readLong();
+        record.mSourceNode = parcel.readParcelable(null);
         record.mSealed = (parcel.readInt() == 1);
     }
 
@@ -1167,7 +1167,10 @@
         parcel.writeParcelable(record.mParcelableData, flags);
         parcel.writeList(record.mText);
         parcel.writeInt(record.mSourceWindowId);
-        parcel.writeLong(record.mSourceNodeId);
+        // create copy of the node here because the node would be recycled just after it is written
+        // to parcel
+        parcel.writeParcelable(record.mSourceNode != null ?
+                AccessibilityNodeInfo.obtain(record.mSourceNode) : null, flags);
         parcel.writeInt(record.mSealed ? 1 : 0);
     }
 
@@ -1191,7 +1194,9 @@
             builder.append("\n");
             builder.append("; ContentChangeTypes: ").append(mContentChangeTypes);
             builder.append("; sourceWindowId: ").append(mSourceWindowId);
-            builder.append("; mSourceNodeId: ").append(mSourceNodeId);
+            if (mSourceNode != null) {
+                builder.append("; mSourceNodeId: ").append(mSourceNode.getSourceNodeId());
+            }
             for (int i = 0; i < getRecordCount(); i++) {
                 final AccessibilityRecord record = getRecord(i);
                 builder.append("  Record ");
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 36de8f3..86ed499 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -2821,7 +2821,7 @@
      * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
      */
     private void initFromParcel(Parcel parcel) {
-        mSealed = (parcel.readInt()  == 1);
+        final boolean sealed = (parcel.readInt()  == 1);
         mSourceNodeId = parcel.readLong();
         mWindowId = parcel.readInt();
         mParentNodeId = parcel.readLong();
@@ -2911,6 +2911,8 @@
                     parcel.readInt() == 1,
                     parcel.readInt() == 1);
         }
+
+        mSealed = sealed;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index cc6a71d..f99690a 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -90,7 +90,7 @@
 
     int mAddedCount= UNDEFINED;
     int mRemovedCount = UNDEFINED;
-    long mSourceNodeId = AccessibilityNodeInfo.makeNodeId(UNDEFINED, UNDEFINED);
+    AccessibilityNodeInfo mSourceNode;
     int mSourceWindowId = UNDEFINED;
 
     CharSequence mClassName;
@@ -135,16 +135,24 @@
      */
     public void setSource(View root, int virtualDescendantId) {
         enforceNotSealed();
-        final boolean important;
-        if (virtualDescendantId == UNDEFINED) {
-            important = (root != null) ? root.isImportantForAccessibility() : true;
-        } else {
-            important = true;
+        boolean important = true;
+        mSourceWindowId = UNDEFINED;
+        clearSourceNode();
+        if (root != null) {
+            if (virtualDescendantId == UNDEFINED ||
+                    virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                important = root.isImportantForAccessibility();
+                mSourceNode = root.createAccessibilityNodeInfo();
+            } else {
+                AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
+                if (provider != null) {
+                    mSourceNode = provider.createAccessibilityNodeInfo(virtualDescendantId);
+                }
+            }
+
+            mSourceWindowId = root.getAccessibilityWindowId();
         }
         setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
-        mSourceWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED;
-        final int rootViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
-        mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
     }
 
     /**
@@ -158,13 +166,11 @@
      */
     public AccessibilityNodeInfo getSource() {
         enforceSealed();
-        if (mConnectionId == UNDEFINED || mSourceWindowId == UNDEFINED
-                || AccessibilityNodeInfo.getAccessibilityViewId(mSourceNodeId) == UNDEFINED) {
-            return null;
+        if (mSourceNode != null) {
+            return AccessibilityNodeInfo.obtain(mSourceNode);
         }
-        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
-                mSourceNodeId, false, GET_SOURCE_PREFETCH_FLAGS);
+
+        return null;
     }
 
     /**
@@ -619,7 +625,7 @@
      * @hide
      */
     public long getSourceNodeId() {
-        return mSourceNodeId;
+        return mSourceNode != null ? mSourceNode.getSourceNodeId() : UNDEFINED;
     }
 
     /**
@@ -633,6 +639,9 @@
     public void setConnectionId(int connectionId) {
         enforceNotSealed();
         mConnectionId = connectionId;
+        if (mSourceNode != null) {
+            mSourceNode.setConnectionId(mConnectionId);
+        }
     }
 
     /**
@@ -644,6 +653,9 @@
      */
     public void setSealed(boolean sealed) {
         mSealed = sealed;
+        if (mSourceNode != null) {
+            mSourceNode.setSealed(sealed);
+        }
     }
 
     /**
@@ -782,7 +794,9 @@
         mParcelableData = record.mParcelableData;
         mText.addAll(record.mText);
         mSourceWindowId = record.mSourceWindowId;
-        mSourceNodeId = record.mSourceNodeId;
+        if (record.mSourceNode != null) {
+            mSourceNode = AccessibilityNodeInfo.obtain(record.mSourceNode);
+        }
         mConnectionId = record.mConnectionId;
     }
 
@@ -807,11 +821,18 @@
         mBeforeText = null;
         mParcelableData = null;
         mText.clear();
-        mSourceNodeId = AccessibilityNodeInfo.makeNodeId(UNDEFINED, UNDEFINED);
+        clearSourceNode();
         mSourceWindowId = UNDEFINED;
         mConnectionId = UNDEFINED;
     }
 
+    private void clearSourceNode() {
+        if (mSourceNode != null) {
+            mSourceNode.recycle();
+            mSourceNode = null;
+        }
+    }
+
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f733eab..e84ba99 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -25,7 +25,7 @@
 import android.annotation.StyleRes;
 import android.annotation.XmlRes;
 import android.app.Activity;
-import android.app.AssistStructure;
+import android.app.assist.AssistStructure;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
@@ -9443,10 +9443,12 @@
     public void onRtlPropertiesChanged(int layoutDirection) {
         super.onRtlPropertiesChanged(layoutDirection);
 
-        mTextDir = getTextDirectionHeuristic();
-
-        if (mLayout != null) {
-            checkForRelayout();
+        final TextDirectionHeuristic newTextDir = getTextDirectionHeuristic();
+        if (mTextDir != newTextDir) {
+            mTextDir = newTextDir;
+            if (mLayout != null) {
+                checkForRelayout();
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index e4ccb4b..b78eca7 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -37,6 +37,9 @@
     public static final int ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
     public static final int ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
     public static final int ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
+    public static final int ACTION_BRIGHTNESS = 218;
+    public static final int ACTION_BRIGHTNESS_AUTO = 219;
+    public static final int BRIGHTNESS_DIALOG = 220;
     // Temporary constants go here, to await migration to MetricsConstants.
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 663c838..aea1585 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -19,6 +19,7 @@
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.NotificationVisibility;
 import android.service.notification.StatusBarNotification;
 
 /** @hide */
@@ -53,8 +54,8 @@
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
     void onNotificationClear(String pkg, String tag, int id, int userId);
-    void onNotificationVisibilityChanged(
-            in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys);
+    void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
+            in NotificationVisibility[] noLongerVisibleKeys);
     void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
     void setSystemUiVisibility(int vis, int mask, String cause);
     void setWindowState(int window, int state);
diff --git a/core/java/com/android/internal/statusbar/NotificationVisibility.aidl b/core/java/com/android/internal/statusbar/NotificationVisibility.aidl
new file mode 100644
index 0000000..c067551
--- /dev/null
+++ b/core/java/com/android/internal/statusbar/NotificationVisibility.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.statusbar;
+
+parcelable NotificationVisibility;
+
diff --git a/core/java/com/android/internal/statusbar/NotificationVisibility.java b/core/java/com/android/internal/statusbar/NotificationVisibility.java
new file mode 100644
index 0000000..2139ad0
--- /dev/null
+++ b/core/java/com/android/internal/statusbar/NotificationVisibility.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.statusbar;
+
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.util.ArrayDeque;
+import java.util.Collection;
+
+public class NotificationVisibility implements Parcelable {
+    private static final String TAG = "NoViz";
+    private static final int MAX_POOL_SIZE = 25;
+    private static ArrayDeque<NotificationVisibility> sPool = new ArrayDeque<>(MAX_POOL_SIZE);
+    private static int sNexrId = 0;
+
+    public String key;
+    public int rank;
+    public boolean visible = true;
+    /*package*/ int id;
+
+    private NotificationVisibility() {
+        id = sNexrId++;
+    }
+
+    private NotificationVisibility(String key, int rank, boolean visibile) {
+        this();
+        this.key = key;
+        this.rank = rank;
+        this.visible = visibile;
+    }
+
+    @Override
+    public String toString() {
+        return "NotificationVisibility(id=" + id
+                + "key=" + key
+                + " rank=" + rank
+                + (visible?" visible":"")
+                + " )";
+    }
+
+    @Override
+    public NotificationVisibility clone() {
+        return obtain(this.key, this.rank, this.visible);
+    }
+
+    @Override
+    public int hashCode() {
+        // allow lookups by key, which _should_ never be null.
+        return key == null ? 0 : key.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+        // allow lookups by key, which _should_ never be null.
+        if (that instanceof NotificationVisibility) {
+            NotificationVisibility thatViz = (NotificationVisibility) that;
+            return (key == null && thatViz.key == null) || key.equals(thatViz.key);
+        }
+        return false;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(this.key);
+        out.writeInt(this.rank);
+        out.writeInt(this.visible ? 1 : 0);
+    }
+
+    private void readFromParcel(Parcel in) {
+        this.key = in.readString();
+        this.rank = in.readInt();
+        this.visible = in.readInt() != 0;
+    }
+
+    /**
+     * Return a new NotificationVisibility instance from the global pool. Allows us to
+     * avoid allocating new objects in many cases.
+     */
+    public static NotificationVisibility obtain(String key, int rank, boolean visible) {
+        NotificationVisibility vo = obtain();
+        vo.key = key;
+        vo.rank = rank;
+        vo.visible = visible;
+        return vo;
+    }
+
+    private static NotificationVisibility obtain(Parcel in) {
+        NotificationVisibility vo = obtain();
+        vo.readFromParcel(in);
+        return vo;
+    }
+
+    private static NotificationVisibility obtain() {
+        synchronized (sPool) {
+            if (!sPool.isEmpty()) {
+                return sPool.poll();
+            }
+        }
+        return new NotificationVisibility();
+    }
+
+    /**
+     * Return a NotificationVisibility instance to the global pool.
+     * <p>
+     * You MUST NOT touch the NotificationVisibility after calling this function because it has
+     * effectively been freed.
+     * </p>
+     */
+    public void recycle() {
+        if (key == null) {
+            // do nothing on multiple recycles
+            return;
+        }
+        key = null;
+        if (sPool.size() < MAX_POOL_SIZE) {
+            synchronized (sPool) {
+                sPool.offer(this);
+            }
+        }
+    }
+
+    /**
+     * Parcelable.Creator that instantiates NotificationVisibility objects
+     */
+    public static final Parcelable.Creator<NotificationVisibility> CREATOR
+            = new Parcelable.Creator<NotificationVisibility>()
+    {
+        public NotificationVisibility createFromParcel(Parcel parcel)
+        {
+            return obtain(parcel);
+        }
+
+        public NotificationVisibility[] newArray(int size)
+        {
+            return new NotificationVisibility[size];
+        }
+    };
+}
+
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index f5f8b1f..c9d609c 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -257,6 +257,8 @@
                     case SENSOR_TYPE_MAGNETIC_FIELD:
                     case SENSOR_TYPE_ACCELEROMETER:
                     case SENSOR_TYPE_GYROSCOPE:
+                    case SENSOR_TYPE_GRAVITY:
+                    case SENSOR_TYPE_LINEAR_ACCELERATION:
                         status = buffer[i].vector.status;
                         break;
                     case SENSOR_TYPE_HEART_RATE:
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 5bef653..63915ed 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -436,6 +436,23 @@
     return fmt;
 }
 
+static jint LegacyCameraDevice_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) {
+    ALOGV("nativeDetectSurfaceDataspace");
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+    int32_t fmt = 0;
+    status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt);
+    if(err != NO_ERROR) {
+        ALOGE("%s: Error while querying surface dataspace  %s (%d).", __FUNCTION__, strerror(-err),
+                err);
+        return err;
+    }
+    return fmt;
+}
+
 static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
           jobject surface, jintArray dimens) {
     ALOGV("nativeGetSurfaceDimens");
@@ -717,6 +734,9 @@
     { "nativeDetectSurfaceType",
     "(Landroid/view/Surface;)I",
     (void *)LegacyCameraDevice_nativeDetectSurfaceType },
+    { "nativeDetectSurfaceDataspace",
+    "(Landroid/view/Surface;)I",
+    (void *)LegacyCameraDevice_nativeDetectSurfaceDataspace },
     { "nativeDetectSurfaceDimens",
     "(Landroid/view/Surface;[I)I",
     (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 91a3c7e..0e2ec6b 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -77,7 +77,7 @@
         jobject receiverWeak, const sp<MessageQueue>& messageQueue) :
         mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
         mMessageQueue(messageQueue), mWaitingForVsync(false) {
-    ALOGV("receiver %p ~ Initializing input event receiver.", this);
+    ALOGV("receiver %p ~ Initializing display event receiver.", this);
 }
 
 NativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index eb28c4d..98c17c0 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -462,6 +462,12 @@
     return event->getActionButton();
 }
 
+static void android_view_MotionEvent_nativeSetActionButton(JNIEnv* env, jclass clazz,
+        jlong nativePtr, jint button) {
+    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+    event->setActionButton(button);
+}
+
 static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
         jlong nativePtr) {
     MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -779,6 +785,9 @@
     { "nativeGetActionButton",
             "(J)I",
             (void*)android_view_MotionEvent_nativeGetActionButton},
+    { "nativeSetActionButton",
+            "(JI)V",
+            (void*)android_view_MotionEvent_nativeSetActionButton},
     { "nativeIsTouchEvent",
             "(J)Z",
             (void*)android_view_MotionEvent_nativeIsTouchEvent },
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f5c89c5..f6cefba 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1851,7 +1851,9 @@
          2. Pre-installed
          3. In the default state (enabled but not explicitly)
          And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
-         that marks the app as carrier privileged. -->
+         that marks the app as carrier privileged. It also grants the app default permissions
+         for Phone and Location. As such, apps MUST only ever be added to this list if they
+         obtain user consent to access their location through other means. -->
     <string-array name="config_disabledUntilUsedPreinstalledCarrierApps" translatable="false" />
 
     <!-- The list of classes that should be added to the notification ranking pipline.
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 18c83b4..9548e51 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -93,11 +93,11 @@
 
     <!-- France: 5 digits, free: 3xxxx, premium [4-8]xxxx, plus EU:
          http://clients.txtnation.com/entries/161972-france-premium-sms-short-code-requirements -->
-    <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}" />
+    <shortcode country="fr" premium="[4-8]\\d{4}" free="3\\d{4}|116\\d{3}|21101" />
 
     <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
          http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf -->
-    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}" />
+    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|887" />
 
     <!-- Georgia: 4 digits, known premium codes listed -->
     <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
@@ -184,6 +184,6 @@
     <shortcode country="ua" pattern="\\d{4}" premium="444[3-9]|70[579]4|7540" />
 
     <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm) -->
-    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" free="87902" />
+    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" free="122|87902" />
 
 </shortcodes>
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java
index 250bad7..515be1d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java
@@ -113,7 +113,7 @@
                 return result;
             } else {
                 throw new InvalidKeySpecException(
-                        "Obtaining RSAPublicKeySpec not supported for " + key.getAlgorithm() + " "
+                        "Obtaining ECPublicKeySpec not supported for " + key.getAlgorithm() + " "
                         + ((key instanceof AndroidKeyStorePrivateKey) ? "private" : "public")
                         + " key");
             }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index 688936c..66509e2 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -31,7 +31,6 @@
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
 import java.util.Arrays;
-import java.util.Date;
 
 import javax.crypto.KeyGeneratorSpi;
 import javax.crypto.SecretKey;
@@ -278,15 +277,11 @@
         KeymasterUtils.addUserAuthArgs(args,
                 spec.isUserAuthenticationRequired(),
                 spec.getUserAuthenticationValidityDurationSeconds());
-        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
-                (spec.getKeyValidityStart() != null)
-                ? spec.getKeyValidityStart() : new Date(0));
-        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                (spec.getKeyValidityForOriginationEnd() != null)
-                ? spec.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE));
-        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                (spec.getKeyValidityForConsumptionEnd() != null)
-                ? spec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                spec.getKeyValidityForOriginationEnd());
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                spec.getKeyValidityForConsumptionEnd());
 
         if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0)
                 && (!spec.isRandomizedEncryptionRequired())) {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index f7ff07f..ff265cf 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -415,15 +415,11 @@
         KeymasterUtils.addUserAuthArgs(args,
                 mSpec.isUserAuthenticationRequired(),
                 mSpec.getUserAuthenticationValidityDurationSeconds());
-        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
-                (mSpec.getKeyValidityStart() != null)
-                ? mSpec.getKeyValidityStart() : new Date(0));
-        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                (mSpec.getKeyValidityForOriginationEnd() != null)
-                ? mSpec.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE));
-        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                (mSpec.getKeyValidityForConsumptionEnd() != null)
-                ? mSpec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                mSpec.getKeyValidityForOriginationEnd());
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                mSpec.getKeyValidityForConsumptionEnd());
         addAlgorithmSpecificParameters(args);
 
         byte[] additionalEntropy =
@@ -515,15 +511,23 @@
             return generateSelfSignedCertificateWithFakeSignature(publicKey);
         } else {
             // Key can be used to sign a certificate
-            return generateSelfSignedCertificateWithValidSignature(
-                    privateKey, publicKey, signatureAlgorithm);
+            try {
+                return generateSelfSignedCertificateWithValidSignature(
+                        privateKey, publicKey, signatureAlgorithm);
+            } catch (Exception e) {
+                // Failed to generate the self-signed certificate with valid signature. Fall back
+                // to generating a self-signed certificate with a fake signature. This is done for
+                // all exception types because we prefer key pair generation to succeed and end up
+                // producing a self-signed certificate with an invalid signature to key pair
+                // generation failing.
+                return generateSelfSignedCertificateWithFakeSignature(publicKey);
+            }
         }
     }
 
     @SuppressWarnings("deprecation")
     private X509Certificate generateSelfSignedCertificateWithValidSignature(
-            PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm)
-                    throws Exception {
+            PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception {
         final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
         certGen.setPublicKey(publicKey);
         certGen.setSerialNumber(mSpec.getCertificateSerialNumber());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 8b00821..7887923 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -147,21 +147,10 @@
         }
 
         Date keyValidityStart = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME);
-        if ((keyValidityStart != null) && (keyValidityStart.getTime() <= 0)) {
-            keyValidityStart = null;
-        }
         Date keyValidityForOriginationEnd =
                 keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME);
-        if ((keyValidityForOriginationEnd != null)
-                && (keyValidityForOriginationEnd.getTime() == Long.MAX_VALUE)) {
-            keyValidityForOriginationEnd = null;
-        }
         Date keyValidityForConsumptionEnd =
                 keyCharacteristics.getDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME);
-        if ((keyValidityForConsumptionEnd != null)
-                && (keyValidityForConsumptionEnd.getTime() == Long.MAX_VALUE)) {
-            keyValidityForConsumptionEnd = null;
-        }
         boolean userAuthenticationRequired =
                 !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
         int userAuthenticationValidityDurationSeconds =
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 5fb589e..084e30e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -435,17 +435,12 @@
                 KeymasterUtils.addUserAuthArgs(importArgs,
                         spec.isUserAuthenticationRequired(),
                         spec.getUserAuthenticationValidityDurationSeconds());
-                importArgs.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
-                        (spec.getKeyValidityStart() != null)
-                                ? spec.getKeyValidityStart() : new Date(0));
-                importArgs.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                        (spec.getKeyValidityForOriginationEnd() != null)
-                                ? spec.getKeyValidityForOriginationEnd()
-                                : new Date(Long.MAX_VALUE));
-                importArgs.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                        (spec.getKeyValidityForConsumptionEnd() != null)
-                                ? spec.getKeyValidityForConsumptionEnd()
-                                : new Date(Long.MAX_VALUE));
+                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
+                        spec.getKeyValidityStart());
+                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                        spec.getKeyValidityForOriginationEnd());
+                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                        spec.getKeyValidityForConsumptionEnd());
             } catch (IllegalArgumentException e) {
                 throw new KeyStoreException("Invalid parameter", e);
             }
@@ -646,15 +641,11 @@
         KeymasterUtils.addUserAuthArgs(args,
                 params.isUserAuthenticationRequired(),
                 params.getUserAuthenticationValidityDurationSeconds());
-        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
-                (params.getKeyValidityStart() != null)
-                        ? params.getKeyValidityStart() : new Date(0));
-        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                (params.getKeyValidityForOriginationEnd() != null)
-                        ? params.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE));
-        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                (params.getKeyValidityForConsumptionEnd() != null)
-                        ? params.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE));
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, params.getKeyValidityStart());
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+                params.getKeyValidityForOriginationEnd());
+        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
+                params.getKeyValidityForConsumptionEnd());
 
         if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
                 && (!params.isRandomizedEncryptionRequired())) {
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 3d23399..919dd48 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -71,6 +71,8 @@
  * <li>{@link KeyProperties#PURPOSE_SIGN},</li>
  * <li>operation without requiring the user to be authenticated (see
  * {@link Builder#setUserAuthenticationRequired(boolean)}),</li>
+ * <li>signing/origination at this moment in time (see {@link Builder#setKeyValidityStart(Date)}
+ * and {@link Builder#setKeyValidityForOriginationEnd(Date)}),</li>
  * <li>suitable digest or {@link KeyProperties#DIGEST_NONE},</li>
  * <li>(RSA keys only) padding scheme {@link KeyProperties#SIGNATURE_PADDING_RSA_PKCS1} or
  * {@link KeyProperties#ENCRYPTION_PADDING_NONE}.</li>
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index d9b40ae..00add29 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -14,15 +14,13 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "OpenGLRenderer"
-#define ATRACE_TAG ATRACE_TAG_VIEW
-
 #include "LayerCache.h"
 #include "LayerRenderer.h"
 #include "Matrix.h"
 #include "Properties.h"
 #include "Rect.h"
 #include "renderstate/RenderState.h"
+#include "utils/GLUtils.h"
 #include "utils/TraceUtils.h"
 
 #include <ui/Rect.h>
@@ -238,8 +236,9 @@
         layer->allocateTexture();
 
         // This should only happen if we run out of memory
-        if (glGetError() != GL_NO_ERROR) {
-            ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
+        if (CC_UNLIKELY(GLUtils::dumpGLErrors())) {
+            LOG_ALWAYS_FATAL("Could not allocate texture for layer (fbo=%d %dx%d)",
+                    fbo, width, height);
             renderState.bindFramebuffer(previousFbo);
             layer->decStrong(nullptr);
             return nullptr;
diff --git a/libs/hwui/utils/GLUtils.cpp b/libs/hwui/utils/GLUtils.cpp
index 9b298ca..55104de 100644
--- a/libs/hwui/utils/GLUtils.cpp
+++ b/libs/hwui/utils/GLUtils.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "OpenGLRenderer"
-
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
@@ -26,9 +24,11 @@
 namespace android {
 namespace uirenderer {
 
-void GLUtils::dumpGLErrors() {
+bool GLUtils::dumpGLErrors() {
+    bool errorObserved = false;
     GLenum status = GL_NO_ERROR;
     while ((status = glGetError()) != GL_NO_ERROR) {
+        errorObserved = true;
         switch (status) {
         case GL_INVALID_ENUM:
             ALOGE("GL error:  GL_INVALID_ENUM");
@@ -46,6 +46,7 @@
             ALOGE("GL error: 0x%x", status);
         }
     }
+    return errorObserved;
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
index 890e374..7020461 100644
--- a/libs/hwui/utils/GLUtils.h
+++ b/libs/hwui/utils/GLUtils.h
@@ -20,12 +20,11 @@
 namespace uirenderer {
 
 class GLUtils {
-private:
 public:
     /**
-     * Print out any GL errors with ALOGE
+     * Print out any GL errors with ALOGE, returns true if any errors were found.
      */
-    static void dumpGLErrors();
+    static bool dumpGLErrors();
 
 }; // class GLUtils
 
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 9609c35..d303a2e 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -150,6 +150,25 @@
 
     /**
      * High speed ( >= 100fps) quality level corresponding to the lowest available resolution.
+     * <p>
+     * For all the high speed profiles defined below ((from {@link #QUALITY_HIGH_SPEED_LOW} to
+     * {@link #QUALITY_HIGH_SPEED_2160P}), they are similar as normal recording profiles, with just
+     * higher output frame rate and bit rate. Therefore, setting these profiles with
+     * {@link MediaRecorder#setProfile} without specifying any other encoding parameters will
+     * produce high speed videos rather than slow motion videos that have different capture and
+     * output (playback) frame rates. To record slow motion videos, the application must set video
+     * output (playback) frame rate and bit rate appropriately via
+     * {@link MediaRecorder#setVideoFrameRate} and {@link MediaRecorder#setVideoEncodingBitRate}
+     * based on the slow motion factor. If the application intends to do the video recording with
+     * {@link MediaCodec} encoder, it must set each individual field of {@link MediaFormat}
+     * similarly according to this CamcorderProfile.
+     * </p>
+     *
+     * @see #videoBitRate
+     * @see #videoFrameRate
+     * @see MediaRecorder
+     * @see MediaCodec
+     * @see MediaFormat
      */
     public static final int QUALITY_HIGH_SPEED_LOW = 2000;
 
@@ -212,11 +231,56 @@
 
     /**
      * The target video output bit rate in bits per second
+     * <p>
+     * This is the target recorded video output bit rate if the application configures the video
+     * recording via {@link MediaRecorder#setProfile} without specifying any other
+     * {@link MediaRecorder} encoding parameters. For example, for high speed quality profiles (from
+     * {@link #QUALITY_HIGH_SPEED_LOW} to {@link #QUALITY_HIGH_SPEED_2160P}), this is the bit rate
+     * where the video is recorded with. If the application intends to record slow motion videos
+     * with the high speed quality profiles, it must set a different video bit rate that is
+     * corresponding to the desired recording output bit rate (i.e., the encoded video bit rate
+     * during normal playback) via {@link MediaRecorder#setVideoEncodingBitRate}. For example, if
+     * {@link #QUALITY_HIGH_SPEED_720P} advertises 240fps {@link #videoFrameRate} and 64Mbps
+     * {@link #videoBitRate} in the high speed CamcorderProfile, and the application intends to
+     * record 1/8 factor slow motion recording videos, the application must set 30fps via
+     * {@link MediaRecorder#setVideoFrameRate} and 8Mbps ( {@link #videoBitRate} * slow motion
+     * factor) via {@link MediaRecorder#setVideoEncodingBitRate}. Failing to do so will result in
+     * videos with unexpected frame rate and bit rate, or {@link MediaRecorder} error if the output
+     * bit rate exceeds the encoder limit. If the application intends to do the video recording with
+     * {@link MediaCodec} encoder, it must set each individual field of {@link MediaFormat}
+     * similarly according to this CamcorderProfile.
+     * </p>
+     *
+     * @see #videoFrameRate
+     * @see MediaRecorder
+     * @see MediaCodec
+     * @see MediaFormat
      */
     public int videoBitRate;
 
     /**
-     * The target video frame rate in frames per second
+     * The target video frame rate in frames per second.
+     * <p>
+     * This is the target recorded video output frame rate per second if the application configures
+     * the video recording via {@link MediaRecorder#setProfile} without specifying any other
+     * {@link MediaRecorder} encoding parameters. For example, for high speed quality profiles (from
+     * {@link #QUALITY_HIGH_SPEED_LOW} to {@link #QUALITY_HIGH_SPEED_2160P}), this is the frame rate
+     * where the video is recorded and played back with. If the application intends to create slow
+     * motion use case with the high speed quality profiles, it must set a different video frame
+     * rate that is corresponding to the desired output (playback) frame rate via
+     * {@link MediaRecorder#setVideoFrameRate}. For example, if {@link #QUALITY_HIGH_SPEED_720P}
+     * advertises 240fps {@link #videoFrameRate} in the CamcorderProfile, and the application
+     * intends to create 1/8 factor slow motion recording videos, the application must set 30fps via
+     * {@link MediaRecorder#setVideoFrameRate}. Failing to do so will result in high speed videos
+     * with normal speed playback frame rate (240fps for above example). If the application intends
+     * to do the video recording with {@link MediaCodec} encoder, it must set each individual field
+     * of {@link MediaFormat} similarly according to this CamcorderProfile.
+     * </p>
+     *
+     * @see #videoBitRate
+     * @see MediaRecorder
+     * @see MediaCodec
+     * @see MediaFormat
      */
     public int videoFrameRate;
 
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index da5f33e..7cd086e 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -710,7 +710,7 @@
         public static final String COLUMN_LOCKED = "locked";
 
         /**
-         * The app badge icon of the app link template for this channel.
+         * The URI for the app badge icon of the app link template for this channel.
          *
          * <p>This small icon is overlaid at the bottom of the poster art specified by
          * {@link #COLUMN_APP_LINK_POSTER_ART_URI}. The data in the column must be a URI in one of
@@ -736,9 +736,10 @@
         public static final String COLUMN_APP_LINK_ICON_URI = "app_link_icon_uri";
 
         /**
-         * The poster art used as the background of the app link template for this channel.
+         * The URI for the poster art used as the background of the app link template for this
+         * channel.
          *
-         * <p>The data in the column must be a URL or a URI in one of the following formats:
+         * <p>The data in the column must be a URL, or a URI in one of the following formats:
          *
          * <ul>
          * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
@@ -1100,6 +1101,15 @@
         /**
          * The URI for the poster art of this TV program.
          *
+         * <p>The data in the column must be a URL, or a URI in one of the following formats:
+         *
+         * <ul>
+         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+         * </li>
+         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+         * </ul>
+         *
          * <p>Can be empty.
          *
          * <p>Type: TEXT
@@ -1109,6 +1119,19 @@
         /**
          * The URI for the thumbnail of this TV program.
          *
+         * <p>The system can generate a thumbnail from the poster art if this column is not
+         * specified. Thus it is not necessary for TV input services to include a thumbnail if it is
+         * just a scaled image of the poster art.
+         *
+         * <p>The data in the column must be a URL, or a URI in one of the following formats:
+         *
+         * <ul>
+         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+         * </li>
+         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+         * </ul>
+         *
          * <p>Can be empty.
          *
          * <p>Type: TEXT
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index f4e4ea1..ef08e19 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -346,7 +346,7 @@
                         accessPoint.update(mLastInfo, mLastNetworkInfo);
                     }
 
-                    if (result.passpointNetwork) {
+                    if (result.isPasspointNetwork()) {
                         WifiConfiguration config = mWifiManager.getMatchingWifiConfig(result);
                         if (config != null) {
                             accessPoint.update(config);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index aff6ad8..44b9d8b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -904,16 +904,16 @@
 
     private boolean mutateSystemSetting(String name, String value, int runAsUserId,
             int operation) {
-        // Make sure the caller can change the settings.
-        enforceWritePermission(Manifest.permission.WRITE_SETTINGS);
+        // Check for permissions first.
+        hasPermissionsToMutateSystemSettings();
 
         // Verify whether this operation is allowed for the calling package.
         if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
             return false;
         }
 
-        // Enforce what the calling package can mutate in the system settings.
-        enforceRestrictedSystemSettingsMutationForCallingPackageLocked(operation, name);
+        // Enforce what the calling package can mutate the system settings.
+        enforceRestrictedSystemSettingsMutationForCallingPackage(operation, name);
 
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
@@ -954,6 +954,28 @@
         }
     }
 
+    private boolean hasPermissionsToMutateSystemSettings() {
+        // Write secure settings is a more protected permission. If caller has it we are good.
+        if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+
+        // The write settings permission gates mutation of system settings.
+        if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SETTINGS)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+
+        // Excpet we let system apps change system settings without the permission.
+        PackageInfo packageInfo = getCallingPackageInfoOrThrow();
+        if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+            return true;
+        }
+
+        return false;
+    }
+
     private void validateSystemSettingValue(String name, String value) {
         Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);
         if (validator != null && !validator.validate(value)) {
@@ -1000,7 +1022,7 @@
         return userId;
     }
 
-    private void enforceRestrictedSystemSettingsMutationForCallingPackageLocked(int operation,
+    private void enforceRestrictedSystemSettingsMutationForCallingPackage(int operation,
             String name) {
         // System/root/shell can mutate whatever secure settings they want.
         final int callingUid = Binder.getCallingUid();
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 674356b..7838119 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -311,4 +311,12 @@
     public void showDisclosure() {
         mAssistDisclosure.postShow();
     }
+
+    public void onUserSwitched(int newUserId) {
+        updateAssistInfo();
+    }
+
+    public void prepareBeforeInvocation() {
+        updateAssistInfo();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index d6a16fa..77c27fa 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -30,6 +30,8 @@
 import android.provider.Settings;
 import android.widget.ImageView;
 
+import com.android.internal.logging.MetricsLogger;
+
 import java.util.ArrayList;
 
 public class BrightnessController implements ToggleSlider.Listener {
@@ -195,12 +197,16 @@
     }
 
     @Override
-    public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value) {
+    public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value,
+            boolean stopTracking) {
         updateIcon(mAutomatic);
         if (mExternalChange) return;
 
         if (!mAutomatic) {
             final int val = value + mMinimumBacklight;
+            if (stopTracking) {
+                MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS, val);
+            }
             setBrightness(val);
             if (!tracking) {
                 AsyncTask.execute(new Runnable() {
@@ -213,6 +219,9 @@
             }
         } else {
             final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;
+            if (stopTracking) {
+                MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS_AUTO, value);
+            }
             setBrightnessAdj(adj);
             if (!tracking) {
                 AsyncTask.execute(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 74267a5..cef4d34 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -24,6 +24,7 @@
 import android.view.WindowManager;
 import android.widget.ImageView;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 
 /** A dialog that provides controls for adjusting the screen brightness. */
@@ -52,11 +53,13 @@
     protected void onStart() {
         super.onStart();
         mBrightnessController.registerCallbacks();
+        MetricsLogger.visible(this, MetricsLogger.BRIGHTNESS_DIALOG);
     }
 
     @Override
     protected void onStop() {
         super.onStop();
+        MetricsLogger.hidden(this, MetricsLogger.BRIGHTNESS_DIALOG);
         mBrightnessController.unregisterCallbacks();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index cdb8e69..d247711 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -35,7 +35,8 @@
 public class ToggleSlider extends RelativeLayout {
     public interface Listener {
         public void onInit(ToggleSlider v);
-        public void onChanged(ToggleSlider v, boolean tracking, boolean checked, int value);
+        public void onChanged(ToggleSlider v, boolean tracking, boolean checked, int value,
+                boolean stopTracking);
     }
 
     private Listener mListener;
@@ -143,7 +144,7 @@
 
             if (mListener != null) {
                 mListener.onChanged(
-                        ToggleSlider.this, mTracking, checked, mSlider.getProgress());
+                        ToggleSlider.this, mTracking, checked, mSlider.getProgress(), false);
             }
 
             if (mMirror != null) {
@@ -157,7 +158,7 @@
         public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
             if (mListener != null) {
                 mListener.onChanged(
-                        ToggleSlider.this, mTracking, mToggle.isChecked(), progress);
+                        ToggleSlider.this, mTracking, mToggle.isChecked(), progress, false);
             }
         }
 
@@ -166,8 +167,8 @@
             mTracking = true;
 
             if (mListener != null) {
-                mListener.onChanged(
-                        ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress());
+                mListener.onChanged(ToggleSlider.this, mTracking, mToggle.isChecked(),
+                        mSlider.getProgress(), false);
             }
 
             mToggle.setChecked(false);
@@ -183,8 +184,8 @@
             mTracking = false;
 
             if (mListener != null) {
-                mListener.onChanged(
-                        ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress());
+                mListener.onChanged(ToggleSlider.this, mTracking, mToggle.isChecked(),
+                        mSlider.getProgress(), true);
             }
 
             if (mMirrorController != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 295fdc8..9d6204c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1613,17 +1613,11 @@
 
     /**
      * The LEDs are turned off when the notification panel is shown, even just a little bit.
-     * This was added last-minute and is inconsistent with the way the rest of the notifications
-     * are handled, because the notification isn't really cancelled.  The lights are just
-     * turned off.  If any other notifications happen, the lights will turn back on.  Steve says
-     * this is what he wants. (see bug 1131461)
      */
     protected void handleVisibleToUserChanged(boolean visibleToUser) {
         try {
             if (visibleToUser) {
-                // Only stop blinking, vibrating, ringing when the user went into the shade
-                // manually (SHADE or SHADE_LOCKED).
-                boolean clearNotificationEffects =
+                boolean clearNotificationEffects = mShowLockscreenNotifications ||
                         (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
                 mBarService.onPanelRevealed(clearNotificationEffects);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 16df64c..9e6dd7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -96,6 +96,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.keyguard.ViewMediatorCallback;
@@ -457,7 +458,8 @@
     private int mDisabledUnmodified2;
 
     /** Keys of notifications currently visible to the user. */
-    private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>();
+    private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications =
+            new ArraySet<>();
     private long mLastVisibilityReportUptimeMs;
 
     private final ShadeUpdates mShadeUpdates = new ShadeUpdates();
@@ -471,9 +473,7 @@
     private int mLastLoggedStateFingerprint;
 
     private static final int VISIBLE_LOCATIONS = StackViewState.LOCATION_FIRST_CARD
-            | StackViewState.LOCATION_TOP_STACK_PEEKING
-            | StackViewState.LOCATION_MAIN_AREA
-            | StackViewState.LOCATION_BOTTOM_STACK_PEEKING;
+            | StackViewState.LOCATION_MAIN_AREA;
 
     private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
             new OnChildLocationsChangedListener() {
@@ -498,12 +498,17 @@
     // Tracks notifications currently visible in mNotificationStackScroller and
     // emits visibility events via NoMan on changes.
     private final Runnable mVisibilityReporter = new Runnable() {
-        private final ArrayList<String> mTmpNewlyVisibleNotifications = new ArrayList<String>();
-        private final ArrayList<String> mTmpCurrentlyVisibleNotifications = new ArrayList<String>();
+        private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications =
+                new ArraySet<>();
+        private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications =
+                new ArraySet<>();
+        private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications =
+                new ArraySet<>();
 
         @Override
         public void run() {
             mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
+            final String mediaKey = getCurrentMediaNotificationKey();
 
             // 1. Loop over mNotificationData entries:
             //   A. Keep list of visible notifications.
@@ -518,31 +523,45 @@
             for (int i = 0; i < N; i++) {
                 Entry entry = activeNotifications.get(i);
                 String key = entry.notification.getKey();
-                boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key);
-                boolean currentlyVisible =
+                boolean isVisible =
                         (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0;
-                if (currentlyVisible) {
+                NotificationVisibility visObj = NotificationVisibility.obtain(key, i, isVisible);
+                boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj);
+                if (isVisible) {
                     // Build new set of visible notifications.
-                    mTmpCurrentlyVisibleNotifications.add(key);
-                }
-                if (!previouslyVisible && currentlyVisible) {
-                    mTmpNewlyVisibleNotifications.add(key);
+                    mTmpCurrentlyVisibleNotifications.add(visObj);
+                    if (!previouslyVisible) {
+                        mTmpNewlyVisibleNotifications.add(visObj);
+                    }
+                } else {
+                    // release object
+                    visObj.recycle();
                 }
             }
-            ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications;
-            noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
+            mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications);
+            mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
 
             logNotificationVisibilityChanges(
-                    mTmpNewlyVisibleNotifications, noLongerVisibleNotifications);
+                    mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications);
 
-            mCurrentlyVisibleNotifications.clear();
+            recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
             mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
 
-            mTmpNewlyVisibleNotifications.clear();
+            recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications);
             mTmpCurrentlyVisibleNotifications.clear();
+            mTmpNewlyVisibleNotifications.clear();
+            mTmpNoLongerVisibleNotifications.clear();
         }
     };
 
+    private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
+        final int N = array.size();
+        for (int i = 0 ; i < N; i++) {
+            array.valueAt(i).recycle();
+        }
+        array.clear();
+    }
+
     private final View.OnClickListener mOverflowClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
@@ -1028,6 +1047,7 @@
     private int mShowSearchHoldoff = 0;
     private Runnable mInvokeAssist = new Runnable() {
         public void run() {
+            mAssistManager.prepareBeforeInvocation();
             invokeAssistGesture(true /* vibrate */);
             awakenDreams();
             if (mNavigationBarView != null) {
@@ -2917,6 +2937,7 @@
         updateNotifications();
         resetUserSetupObserver();
         setControllerUsers();
+        mAssistManager.onUserSwitched(newUserId);
     }
 
     private void setControllerUsers() {
@@ -2987,9 +3008,9 @@
         // Report all notifications as invisible and turn down the
         // reporter.
         if (!mCurrentlyVisibleNotifications.isEmpty()) {
-            logNotificationVisibilityChanges(
-                    Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
-            mCurrentlyVisibleNotifications.clear();
+            logNotificationVisibilityChanges(Collections.<NotificationVisibility>emptyList(),
+                    mCurrentlyVisibleNotifications);
+            recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
         }
         mHandler.removeCallbacks(mVisibilityReporter);
         mStackScroller.setChildLocationsChangedListener(null);
@@ -3007,18 +3028,27 @@
     }
 
     private void logNotificationVisibilityChanges(
-            Collection<String> newlyVisible, Collection<String> noLongerVisible) {
+            Collection<NotificationVisibility> newlyVisible,
+            Collection<NotificationVisibility> noLongerVisible) {
         if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
             return;
         }
-        String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]);
-        String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]);
+        NotificationVisibility[] newlyVisibleAr =
+                newlyVisible.toArray(new NotificationVisibility[newlyVisible.size()]);
+        NotificationVisibility[] noLongerVisibleAr =
+                noLongerVisible.toArray(new NotificationVisibility[noLongerVisible.size()]);
         try {
             mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
         } catch (RemoteException e) {
             // Ignore.
         }
-        setNotificationsShown(newlyVisibleAr);
+
+        final int N = newlyVisible.size();
+        String[] newlyVisibleKeyAr = new String[N];
+        for (int i = 0; i < N; i++) {
+            newlyVisibleKeyAr[i] = newlyVisibleAr[i].key;
+        }
+        setNotificationsShown(newlyVisibleKeyAr);
     }
 
     // State logging
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index 2b76c31..a5b244e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -150,13 +150,23 @@
     }
 
     public void onStartDrag() {
-        mDropTarget.setVisibility(View.VISIBLE);
-        mAddTarget.setVisibility(View.GONE);
+        mDropTarget.post(new Runnable() {
+            @Override
+            public void run() {
+                mDropTarget.setVisibility(View.VISIBLE);
+                mAddTarget.setVisibility(View.GONE);
+            }
+        });
     }
 
     public void stopDrag() {
-        mDropTarget.setVisibility(View.GONE);
-        mAddTarget.setVisibility(View.VISIBLE);
+        mDropTarget.post(new Runnable() {
+            @Override
+            public void run() {
+                mDropTarget.setVisibility(View.GONE);
+                mAddTarget.setVisibility(View.VISIBLE);
+            }
+        });
     }
 
     @Override
@@ -230,9 +240,16 @@
 
         public void showAddDialog() {
             List<String> tiles = mTileSpecs;
+            int numBroadcast = 0;
+            for (int i = 0; i < tiles.size(); i++) {
+                if (tiles.get(i).startsWith(IntentTile.PREFIX)) {
+                    numBroadcast++;
+                }
+            }
             String[] defaults =
                 getContext().getString(R.string.quick_settings_tiles_default).split(",");
-            final String[] available = new String[defaults.length + 1 - tiles.size()];
+            final String[] available = new String[defaults.length + 1
+                                                  - (tiles.size() - numBroadcast)];
             final String[] availableTiles = new String[available.length];
             int index = 0;
             for (int i = 0; i < defaults.length; i++) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 25d4d5e..d9e5b75 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -23,6 +23,7 @@
 import static android.net.ConnectivityManager.TYPE_VPN;
 import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
@@ -1869,7 +1870,14 @@
                     if (nai == null) {
                         loge("EVENT_NETWORK_CAPABILITIES_CHANGED from unknown NetworkAgent");
                     } else {
-                        updateCapabilities(nai, (NetworkCapabilities)msg.obj);
+                        final NetworkCapabilities networkCapabilities =
+                                (NetworkCapabilities)msg.obj;
+                        if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
+                                networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
+                            Slog.wtf(TAG, "BUG: " + nai + " has stateful capability.");
+                        }
+                        updateCapabilities(nai, networkCapabilities,
+                                NascentState.NOT_JUST_VALIDATED);
                     }
                     break;
                 }
@@ -1956,20 +1964,16 @@
                     if (isLiveNetworkAgent(nai, "EVENT_NETWORK_TESTED")) {
                         final boolean valid =
                                 (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
-                        final boolean validationChanged = (valid != nai.lastValidated);
-                        nai.lastValidated = valid;
-                        if (valid) {
-                            if (DBG) log("Validated " + nai.name());
-                            nai.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
-                            if (!nai.everValidated) {
-                                nai.everValidated = true;
-                                rematchNetworkAndRequests(nai, NascentState.JUST_VALIDATED,
-                                    ReapUnvalidatedNetworks.REAP);
-                                // If score has changed, rebroadcast to NetworkFactories. b/17726566
-                                sendUpdatedScoreToFactories(nai);
-                            }
-                        } else {
-                            nai.networkCapabilities.removeCapability(NET_CAPABILITY_VALIDATED);
+                        if (DBG) log(nai.name() + " validation " + (valid ? " passed" : "failed"));
+                        if (valid != nai.lastValidated) {
+                            final int oldScore = nai.getCurrentScore();
+                            final NascentState nascent = (valid && !nai.everValidated) ?
+                                    NascentState.JUST_VALIDATED : NascentState.NOT_JUST_VALIDATED;
+                            nai.lastValidated = valid;
+                            nai.everValidated |= valid;
+                            updateCapabilities(nai, nai.networkCapabilities, nascent);
+                            // If score has changed, rebroadcast to NetworkFactories. b/17726566
+                            if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
                         }
                         updateInetCondition(nai);
                         // Let the NetworkAgent know the state of its network
@@ -1977,10 +1981,6 @@
                                 android.net.NetworkAgent.CMD_REPORT_NETWORK_STATUS,
                                 (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
                                 0, null);
-
-                        if (validationChanged) {
-                            notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
-                        }
                     }
                     break;
                 }
@@ -1993,18 +1993,25 @@
                 }
                 case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
                     final int netId = msg.arg2;
-                    if (msg.arg1 == 0) {
+                    final boolean visible = (msg.arg1 != 0);
+                    final NetworkAgentInfo nai;
+                    synchronized (mNetworkForNetId) {
+                        nai = mNetworkForNetId.get(netId);
+                    }
+                    // If captive portal status has changed, update capabilities.
+                    if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
+                        nai.lastCaptivePortalDetected = visible;
+                        nai.everCaptivePortalDetected |= visible;
+                        updateCapabilities(nai, nai.networkCapabilities,
+                                NascentState.NOT_JUST_VALIDATED);
+                    }
+                    if (!visible) {
                         setProvNotificationVisibleIntent(false, netId, null, 0, null, null);
                     } else {
-                        final NetworkAgentInfo nai;
-                        synchronized (mNetworkForNetId) {
-                            nai = mNetworkForNetId.get(netId);
-                        }
                         if (nai == null) {
                             loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
                             break;
                         }
-                        nai.captivePortalDetected = true;
                         setProvNotificationVisibleIntent(true, netId, NotificationType.SIGN_IN,
                                 nai.networkInfo.getType(),nai.networkInfo.getExtraInfo(),
                                 (PendingIntent)msg.obj);
@@ -2390,7 +2397,7 @@
         if (accept != nai.networkMisc.acceptUnvalidated) {
             int oldScore = nai.getCurrentScore();
             nai.networkMisc.acceptUnvalidated = accept;
-            rematchAllNetworksAndRequests(nai, oldScore);
+            rematchAllNetworksAndRequests(nai, oldScore, NascentState.NOT_JUST_VALIDATED);
             sendUpdatedScoreToFactories(nai);
         }
 
@@ -2426,7 +2433,7 @@
         // Only prompt if the network is unvalidated and was explicitly selected by the user, and if
         // we haven't already been told to switch to it regardless of whether it validated or not.
         // Also don't prompt on captive portals because we're already prompting the user to sign in.
-        if (nai == null || nai.everValidated || nai.captivePortalDetected ||
+        if (nai == null || nai.everValidated || nai.everCaptivePortalDetected ||
                 !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) {
             return;
         }
@@ -3571,12 +3578,24 @@
         }
     }
 
+    private void ensureImmutableCapabilities(NetworkCapabilities networkCapabilities) {
+        if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
+            throw new IllegalArgumentException(
+                    "Cannot request network with NET_CAPABILITY_VALIDATED");
+        }
+        if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) {
+            throw new IllegalArgumentException(
+                    "Cannot request network with NET_CAPABILITY_CAPTIVE_PORTAL");
+        }
+    }
+
     @Override
     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
             Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities);
         enforceMeteredApnPolicy(networkCapabilities);
+        ensureImmutableCapabilities(networkCapabilities);
 
         if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
             throw new IllegalArgumentException("Bad timeout specified");
@@ -3645,6 +3664,7 @@
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities);
         enforceMeteredApnPolicy(networkCapabilities);
+        ensureImmutableCapabilities(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId());
@@ -4046,18 +4066,35 @@
         mNumDnsEntries = last;
     }
 
+    /**
+     * Update the NetworkCapabilities for {@code networkAgent} to {@code networkCapabilities}
+     * augmented with any stateful capabilities implied from {@code networkAgent}
+     * (e.g., validated status and captive portal status).
+     *
+     * @param networkAgent the network having its capabilities updated.
+     * @param networkCapabilities the new network capabilities.
+     * @param nascent indicates whether {@code networkAgent} was validated
+     *         (i.e. had everValidated set for the first time) immediately prior to this call.
+     */
     private void updateCapabilities(NetworkAgentInfo networkAgent,
-            NetworkCapabilities networkCapabilities) {
+            NetworkCapabilities networkCapabilities, NascentState nascent) {
+        // Don't modify caller's NetworkCapabilities.
+        networkCapabilities = new NetworkCapabilities(networkCapabilities);
+        if (networkAgent.lastValidated) {
+            networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
+        } else {
+            networkCapabilities.removeCapability(NET_CAPABILITY_VALIDATED);
+        }
+        if (networkAgent.lastCaptivePortalDetected) {
+            networkCapabilities.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        } else {
+            networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        }
         if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) {
             synchronized (networkAgent) {
                 networkAgent.networkCapabilities = networkCapabilities;
             }
-            if (networkAgent.lastValidated) {
-                networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
-                // There's no need to remove the capability if we think the network is unvalidated,
-                // because NetworkAgents don't set the validated capability.
-            }
-            rematchAllNetworksAndRequests(networkAgent, networkAgent.getCurrentScore());
+            rematchAllNetworksAndRequests(networkAgent, networkAgent.getCurrentScore(), nascent);
             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_CAP_CHANGED);
         }
     }
@@ -4401,15 +4438,21 @@
         }
     }
 
-    // Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
-    // being disconnected.
-    // If only one Network's score or capabilities have been modified since the last time
-    // this function was called, pass this Network in via the "changed" arugment, otherwise
-    // pass null.
-    // If only one Network has been changed but its NetworkCapabilities have not changed,
-    // pass in the Network's score (from getCurrentScore()) prior to the change via
-    // "oldScore", otherwise pass changed.getCurrentScore() or 0 if "changed" is null.
-    private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
+    /**
+     * Attempt to rematch all Networks with NetworkRequests.  This may result in Networks
+     * being disconnected.
+     * @param changed If only one Network's score or capabilities have been modified since the last
+     *         time this function was called, pass this Network in this argument, otherwise pass
+     *         null.
+     * @param oldScore If only one Network has been changed but its NetworkCapabilities have not
+     *         changed, pass in the Network's score (from getCurrentScore()) prior to the change via
+     *         this argument, otherwise pass {@code changed.getCurrentScore()} or 0 if
+     *         {@code changed} is {@code null}. This is because NetworkCapabilities influence a
+     *         network's score.
+     * @param nascent indicates if {@code changed} has just been validated.
+     */
+    private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore,
+            NascentState nascent) {
         // TODO: This may get slow.  The "changed" parameter is provided for future optimization
         // to avoid the slowness.  It is not simply enough to process just "changed", for
         // example in the case where "changed"'s score decreases and another network should begin
@@ -4418,9 +4461,9 @@
         // Optimization: Only reprocess "changed" if its score improved.  This is safe because it
         // can only add more NetworkRequests satisfied by "changed", and this is exactly what
         // rematchNetworkAndRequests() handles.
-        if (changed != null && oldScore < changed.getCurrentScore()) {
-            rematchNetworkAndRequests(changed, NascentState.NOT_JUST_VALIDATED,
-                    ReapUnvalidatedNetworks.REAP);
+        if (changed != null &&
+                (oldScore < changed.getCurrentScore() || nascent == NascentState.JUST_VALIDATED)) {
+            rematchNetworkAndRequests(changed, nascent, ReapUnvalidatedNetworks.REAP);
         } else {
             for (Iterator i = mNetworkAgentInfos.values().iterator(); i.hasNext(); ) {
                 rematchNetworkAndRequests((NetworkAgentInfo)i.next(),
@@ -4547,7 +4590,7 @@
         final int oldScore = nai.getCurrentScore();
         nai.setCurrentScore(score);
 
-        rematchAllNetworksAndRequests(nai, oldScore);
+        rematchAllNetworksAndRequests(nai, oldScore, NascentState.NOT_JUST_VALIDATED);
 
         sendUpdatedScoreToFactories(nai);
     }
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 49d4c22..43b640b 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -74,7 +74,7 @@
 # when a notification has been canceled
 27530 notification_canceled (key|3),(reason|1),(lifespan|1),(freshness|1),(exposure|1)
 # replaces 27510 with a row per notification
-27531 notification_visibility (key|3),(visibile|1),(lifespan|1),(freshness|1)
+27531 notification_visibility (key|3),(visibile|1),(lifespan|1),(freshness|1),(exposure|1),(rank|1)
 # a notification emited noise, vibration, or light
 27532 notification_alert (key|3),(buzz|1),(beep|1),(blink|1)
 
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index baa55e7..7afb192 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -214,9 +214,9 @@
      */
     @GuardedBy("mQuotaLock")
     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
-
-    private boolean mStandbyChainEnabled = false;
-    private boolean mDozableChainEnabled = false;
+    /** Set of states for the child firewall chains. True if the chain is active. */
+    @GuardedBy("mQuotaLock")
+    final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
 
     private Object mIdleTimerLock = new Object();
     /** Set of interfaces with active idle timers. */
@@ -307,9 +307,6 @@
     }
 
     public void systemReady() {
-        // init firewall states
-        mDozableChainEnabled = false;
-        mStandbyChainEnabled = true;
         prepareNativeDaemon();
         if (DBG) Slog.d(TAG, "Prepared");
     }
@@ -611,7 +608,7 @@
                             uidFirewallRules.valueAt(i));
                 }
             }
-            if (mStandbyChainEnabled) {
+            if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)) {
                 setFirewallChainEnabled(FIREWALL_CHAIN_STANDBY, true);
             }
 
@@ -625,7 +622,7 @@
                             uidFirewallRules.valueAt(i));
                 }
             }
-            if (mDozableChainEnabled) {
+            if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
                 setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
             }
         }
@@ -2013,24 +2010,31 @@
     @Override
     public void setFirewallChainEnabled(int chain, boolean enable) {
         enforceSystemUid();
-        final String operation = enable ? "enable_chain" : "disable_chain";
-        try {
-            String chainName;
-            switch(chain) {
-                case FIREWALL_CHAIN_STANDBY:
-                    chainName = FIREWALL_CHAIN_NAME_STANDBY;
-                    mStandbyChainEnabled = enable;
-                    break;
-                case FIREWALL_CHAIN_DOZABLE:
-                    chainName = FIREWALL_CHAIN_NAME_DOZABLE;
-                    mDozableChainEnabled = enable;
-                    break;
-                default:
-                    throw new IllegalArgumentException("Bad child chain: " + chain);
+        synchronized (mQuotaLock) {
+            if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
+                    mFirewallChainStates.get(chain) == enable) {
+                // All is the same, nothing to do.
+                return;
             }
-            mConnector.execute("firewall", operation, chainName);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mFirewallChainStates.put(chain, enable);
+
+            final String operation = enable ? "enable_chain" : "disable_chain";
+            try {
+                String chainName;
+                switch(chain) {
+                    case FIREWALL_CHAIN_STANDBY:
+                        chainName = FIREWALL_CHAIN_NAME_STANDBY;
+                        break;
+                    case FIREWALL_CHAIN_DOZABLE:
+                        chainName = FIREWALL_CHAIN_NAME_DOZABLE;
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Bad child chain: " + chain);
+                }
+                mConnector.execute("firewall", operation, chainName);
+            } catch (NativeDaemonConnectorException e) {
+                throw e.rethrowAsParcelableException();
+            }
         }
     }
 
@@ -2048,27 +2052,29 @@
     @Override
     public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
         enforceSystemUid();
-        SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
-        SparseIntArray newRules = new SparseIntArray();
-        // apply new set of rules
-        for (int index = uids.length - 1; index >= 0; --index) {
-            int uid = uids[index];
-            int rule = rules[index];
-            setFirewallUidRule(chain, uid, rule);
-            newRules.put(uid, rule);
-        }
-        // collect the rules to remove.
-        SparseIntArray rulesToRemove = new SparseIntArray();
-        for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
-            int uid = uidFirewallRules.keyAt(index);
-            if (newRules.indexOfKey(uid) < 0) {
-                rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
+        synchronized (mQuotaLock) {
+            SparseIntArray uidFirewallRules = getUidFirewallRules(chain);
+            SparseIntArray newRules = new SparseIntArray();
+            // apply new set of rules
+            for (int index = uids.length - 1; index >= 0; --index) {
+                int uid = uids[index];
+                int rule = rules[index];
+                setFirewallUidRule(chain, uid, rule);
+                newRules.put(uid, rule);
             }
-        }
-        // remove dead rules
-        for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
-            int uid = rulesToRemove.keyAt(index);
-            setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT);
+            // collect the rules to remove.
+            SparseIntArray rulesToRemove = new SparseIntArray();
+            for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
+                int uid = uidFirewallRules.keyAt(index);
+                if (newRules.indexOfKey(uid) < 0) {
+                    rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
+                }
+            }
+            // remove dead rules
+            for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
+                int uid = rulesToRemove.keyAt(index);
+                setFirewallUidRuleInternal(chain, uid, FIREWALL_RULE_DEFAULT);
+            }
         }
     }
 
@@ -2094,34 +2100,43 @@
             }
 
             try {
-                String ruleName;
-                if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
-                    if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
-                        ruleName = "allow";
-                    } else {
-                        ruleName = "deny";
-                    }
-                } else { // Blacklist mode
-                    if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
-                        ruleName = "deny";
-                    } else {
-                        ruleName = "allow";
-                    }
-                }
+                String ruleName = getFirewallRuleName(chain, rule);
+                String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
 
                 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
                     uidFirewallRules.delete(uid);
                 } else {
                     uidFirewallRules.put(uid, rule);
                 }
-                mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
-                        ruleName);
+
+                if (!ruleName.equals(oldRuleName)) {
+                    mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
+                            ruleName);
+                }
             } catch (NativeDaemonConnectorException e) {
                 throw e.rethrowAsParcelableException();
             }
         }
     }
 
+    private @NonNull String getFirewallRuleName(int chain, int rule) {
+        String ruleName;
+        if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
+            if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
+                ruleName = "allow";
+            } else {
+                ruleName = "deny";
+            }
+        } else { // Blacklist mode
+            if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
+                ruleName = "deny";
+            } else {
+                ruleName = "allow";
+            }
+        }
+        return ruleName;
+    }
+
     private @NonNull SparseIntArray getUidFirewallRules(int chain) {
         switch (chain) {
             case FIREWALL_CHAIN_STANDBY:
@@ -2272,7 +2287,8 @@
             pw.println("]");
         }
 
-        pw.println("UID firewall standby chain enabled: " + mStandbyChainEnabled);
+        pw.println("UID firewall standby chain enabled: " +
+                mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
         synchronized (mUidFirewallStandbyRules) {
             pw.print("UID firewall standby rule: [");
             final int size = mUidFirewallStandbyRules.size();
@@ -2285,7 +2301,8 @@
             pw.println("]");
         }
 
-        pw.println("UID firewall dozable chain enabled: " + mDozableChainEnabled);
+        pw.println("UID firewall dozable chain enabled: " +
+                mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
         synchronized (mUidFirewallDozableRules) {
             pw.print("UID firewall dozable rule: [");
             final int size = mUidFirewallDozableRules.size();
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index 9347c24..0be24f4 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -16,7 +16,10 @@
 package com.android.server.camera;
 
 import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.UserInfo;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceProxy;
@@ -67,6 +70,32 @@
 
     private final Object mLock = new Object();
     private Set<Integer> mEnabledCameraUsers;
+    private int mLastUser;
+
+    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (action == null) return;
+
+            switch (action) {
+                case Intent.ACTION_USER_ADDED:
+                case Intent.ACTION_USER_REMOVED:
+                case Intent.ACTION_USER_INFO_CHANGED:
+                case Intent.ACTION_MANAGED_PROFILE_ADDED:
+                case Intent.ACTION_MANAGED_PROFILE_REMOVED:
+                    synchronized(mLock) {
+                        // Return immediately if we haven't seen any users start yet
+                        if (mEnabledCameraUsers == null) return;
+                        switchUserLocked(mLastUser);
+                    }
+                    break;
+                default:
+                    break; // do nothing
+            }
+
+        }
+    };
 
     private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
         @Override
@@ -103,6 +132,15 @@
             // Should never see this unless someone messes up the SystemServer service boot order.
             throw new IllegalStateException("UserManagerService must start before CameraService!");
         }
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_ADDED);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
+        filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+        mContext.registerReceiver(mIntentReceiver, filter);
+
         publishBinderService(CAMERA_SERVICE_PROXY_BINDER_NAME, mCameraServiceProxy);
     }
 
@@ -125,6 +163,7 @@
 
     private void switchUserLocked(int userHandle) {
         Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
+        mLastUser = userHandle;
         if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
             // Some user handles have been added or removed, update mediaserver.
             mEnabledCameraUsers = currentUserHandles;
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 3bf1183..51c6628 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -45,6 +45,7 @@
     // This Network object is always valid.
     public final Network network;
     public LinkProperties linkProperties;
+    // This should only be modified via ConnectivityService.updateCapabilities().
     public NetworkCapabilities networkCapabilities;
     public final NetworkMonitor networkMonitor;
     public final NetworkMisc networkMisc;
@@ -66,7 +67,10 @@
 
     // Whether a captive portal was ever detected on this network.
     // This is a sticky bit; once set it is never cleared.
-    public boolean captivePortalDetected;
+    public boolean everCaptivePortalDetected;
+
+    // Whether a captive portal was found during the last network validation attempt.
+    public boolean lastCaptivePortalDetected;
 
     // This represents the last score received from the NetworkAgent.
     private int currentScore;
@@ -174,7 +178,8 @@
                 "created{" + created + "}  " +
                 "explicitlySelected{" + networkMisc.explicitlySelected + "} " +
                 "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " +
-                "captivePortalDetected{" + captivePortalDetected + "} " +
+                "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " +
+                "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " +
                 "}";
     }
 
diff --git a/services/core/java/com/android/server/content/AppIdleMonitor.java b/services/core/java/com/android/server/content/AppIdleMonitor.java
index 9598de8..fe5c2da 100644
--- a/services/core/java/com/android/server/content/AppIdleMonitor.java
+++ b/services/core/java/com/android/server/content/AppIdleMonitor.java
@@ -18,11 +18,6 @@
 
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
 import android.os.UserHandle;
 
 import com.android.server.LocalServices;
@@ -31,53 +26,32 @@
  * Helper to listen for app idle and charging status changes and restart backed off
  * sync operations.
  */
-class AppIdleMonitor implements AppIdleStateChangeListener {
+class AppIdleMonitor extends AppIdleStateChangeListener {
 
     private final SyncManager mSyncManager;
     private final UsageStatsManagerInternal mUsageStats;
-    final BatteryManager mBatteryManager;
-    /** Is the device currently plugged into power. */
-    private boolean mPluggedIn;
+    private boolean mAppIdleParoleOn;
 
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            onPluggedIn(mBatteryManager.isCharging());
-        }
-    };
-
-    AppIdleMonitor(SyncManager syncManager, Context context) {
+    AppIdleMonitor(SyncManager syncManager) {
         mSyncManager = syncManager;
         mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
+        mAppIdleParoleOn = mUsageStats.isAppIdleParoleOn();
+
         mUsageStats.addAppIdleStateChangeListener(this);
-        mBatteryManager = context.getSystemService(BatteryManager.class);
-        mPluggedIn = isPowered();
-        registerReceivers(context);
     }
 
-    private void registerReceivers(Context context) {
-        // Monitor battery charging state
-        IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
-        filter.addAction(BatteryManager.ACTION_DISCHARGING);
-        context.registerReceiver(mReceiver, filter);
-    }
-
-    private boolean isPowered() {
-        return mBatteryManager.isCharging();
-    }
-
-    void onPluggedIn(boolean pluggedIn) {
-        if (mPluggedIn == pluggedIn) {
+    void setAppIdleParoleOn(boolean appIdleParoleOn) {
+        if (mAppIdleParoleOn == appIdleParoleOn) {
             return;
         }
-        mPluggedIn = pluggedIn;
-        if (mPluggedIn) {
+        mAppIdleParoleOn = appIdleParoleOn;
+        if (mAppIdleParoleOn) {
             mSyncManager.onAppNotIdle(null, UserHandle.USER_ALL);
         }
     }
 
     boolean isAppIdle(String packageName, int userId) {
-        return !mPluggedIn && mUsageStats.isAppIdle(packageName, userId);
+        return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, userId);
     }
 
     @Override
@@ -86,4 +60,9 @@
         if (idle) return;
         mSyncManager.onAppNotIdle(packageName, userId);
     }
+
+    @Override
+    public void onParoleStateChanged(boolean isParoleOn) {
+        setAppIdleParoleOn(isParoleOn);
+    }
 }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 7415b0e..658f6f8 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -19,6 +19,7 @@
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
 import android.accounts.AccountManager;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.AppGlobals;
@@ -461,7 +462,7 @@
         mSyncAlarmIntent = PendingIntent.getBroadcast(
                 mContext, 0 /* ignored */, new Intent(ACTION_SYNC_ALARM), 0);
 
-        mAppIdleMonitor = new AppIdleMonitor(this, mContext);
+        mAppIdleMonitor = new AppIdleMonitor(this);
 
         IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
         context.registerReceiver(mConnectivityIntentReceiver, intentFilter);
@@ -1271,7 +1272,7 @@
      * @param userId The user for which the package has become active. Can be USER_ALL if
      * the device just plugged in.
      */
-    void onAppNotIdle(String packageName, int userId) {
+    void onAppNotIdle(@Nullable String packageName, int userId) {
         synchronized (mSyncQueue) {
             // For all sync operations in sync queue, if marked as idle, compare with package name
             // and unmark. And clear backoff for the operation.
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 35fbef6..8d2687b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -231,6 +231,9 @@
     // The elapsed real time when the screen on was blocked.
     private long mScreenOnBlockStartRealTime;
 
+    // True if we told the window manager policy that the screen was off.
+    private boolean mReportedScreenOffToPolicy;
+
     // Remembers whether certain kinds of brightness adjustments
     // were recently applied so that we can decide how to transition.
     private boolean mAppliedAutoBrightness;
@@ -764,24 +767,30 @@
             } catch (RemoteException ex) {
                 // same process
             }
-
-            // Tell the window manager what's happening.
-            // Temporarily block turning the screen on until the window manager is ready
-            // by leaving a black surface covering the screen.  This surface is essentially
-            // the final state of the color fade animation.
-            boolean isOn = (state != Display.STATE_OFF);
-            if (wasOn && !isOn) {
-                unblockScreenOn();
-                mWindowManagerPolicy.screenTurnedOff();
-            } else if (!wasOn && isOn) {
-                if (mPowerState.getColorFadeLevel() == 0.0f) {
-                    blockScreenOn();
-                } else {
-                    unblockScreenOn();
-                }
-                mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
-            }
         }
+
+        // Tell the window manager policy when the screen is turned off or on unless it's due
+        // to the proximity sensor.  We temporarily block turning the screen on until the
+        // window manager is ready by leaving a black surface covering the screen.
+        // This surface is essentially the final state of the color fade animation and
+        // it is only removed once the window manager tells us that the activity has
+        // finished drawing underneath.
+        final boolean isOff = (state == Display.STATE_OFF);
+        if (isOff && !mReportedScreenOffToPolicy && !mScreenOffBecauseOfProximity) {
+            mReportedScreenOffToPolicy = true;
+            unblockScreenOn();
+            mWindowManagerPolicy.screenTurnedOff();
+        } else if (!isOff && mReportedScreenOffToPolicy) {
+            mReportedScreenOffToPolicy = false;
+            if (mPowerState.getColorFadeLevel() == 0.0f) {
+                blockScreenOn();
+            } else {
+                unblockScreenOn();
+            }
+            mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
+        }
+
+        // Return true if the screen isn't blocked.
         return mPendingScreenOnUnblocker == null;
     }
 
@@ -1086,6 +1095,7 @@
         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
         pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
         pw.println("  mPendingScreenOff=" + mPendingScreenOff);
+        pw.println("  mReportedScreenOffToPolicy=" + mReportedScreenOffToPolicy);
 
         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
                 mScreenBrightnessRampAnimator.isAnimating());
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index 98fb11b..02d4f40 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -17,12 +17,7 @@
 package com.android.server.job.controllers;
 
 import android.app.usage.UsageStatsManagerInternal;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
 import android.util.Slog;
 
 import com.android.server.LocalServices;
@@ -38,8 +33,7 @@
  * for a certain amount of time (maybe hours or days) are considered idle. When the app comes
  * out of idle state, it will be allowed to run scheduled jobs.
  */
-public class AppIdleController extends StateController
-        implements UsageStatsManagerInternal.AppIdleStateChangeListener {
+public class AppIdleController extends StateController {
 
     private static final String LOG_TAG = "AppIdleController";
     private static final boolean DEBUG = false;
@@ -49,14 +43,7 @@
     private static volatile AppIdleController sController;
     final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
     private final UsageStatsManagerInternal mUsageStatsInternal;
-    private final BatteryManager mBatteryManager;
-    private boolean mPluggedIn;
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override public void onReceive(Context context, Intent intent) {
-            onPluggedIn(mBatteryManager.isCharging());
-        }
-    };
+    boolean mAppIdleParoleOn;
 
     public static AppIdleController get(JobSchedulerService service) {
         synchronized (sCreationLock) {
@@ -70,17 +57,8 @@
     private AppIdleController(StateChangedListener stateChangedListener, Context context) {
         super(stateChangedListener, context);
         mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
-        mBatteryManager = context.getSystemService(BatteryManager.class);
-        mPluggedIn = mBatteryManager.isCharging();
-        mUsageStatsInternal.addAppIdleStateChangeListener(this);
-        registerReceivers();
-    }
-
-    private void registerReceivers() {
-        // Monitor battery charging state
-        IntentFilter filter = new IntentFilter(BatteryManager.ACTION_CHARGING);
-        filter.addAction(BatteryManager.ACTION_DISCHARGING);
-        mContext.registerReceiver(mReceiver, filter);
+        mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
+        mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
     }
 
     @Override
@@ -88,7 +66,7 @@
         synchronized (mTrackedTasks) {
             mTrackedTasks.add(jobStatus);
             String packageName = jobStatus.job.getService().getPackageName();
-            final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
+            final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
                     jobStatus.getUserId());
             if (DEBUG) {
                 Slog.d(LOG_TAG, "Start tracking, setting idle state of "
@@ -108,7 +86,7 @@
     @Override
     public void dumpControllerState(PrintWriter pw) {
         pw.println("AppIdle");
-        pw.println("Plugged In: " + mPluggedIn);
+        pw.println("Parole On: " + mAppIdleParoleOn);
         synchronized (mTrackedTasks) {
             for (JobStatus task : mTrackedTasks) {
                 pw.print(task.job.getService().getPackageName());
@@ -119,48 +97,20 @@
         }
     }
 
-    @Override
-    public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
-        boolean changed = false;
-        synchronized (mTrackedTasks) {
-            // If currently plugged in, we don't care about app idle state
-            if (mPluggedIn) {
-                return;
-            }
-            for (JobStatus task : mTrackedTasks) {
-                if (task.job.getService().getPackageName().equals(packageName)
-                        && task.getUserId() == userId) {
-                    if (task.appNotIdleConstraintSatisfied.get() != !idle) {
-                        if (DEBUG) {
-                            Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
-                                    + packageName + " to " + idle);
-                        }
-                        task.appNotIdleConstraintSatisfied.set(!idle);
-                        changed = true;
-                    }
-                }
-            }
-        }
-        if (changed) {
-            mStateChangedListener.onControllerStateChanged();
-        }
-    }
-
-    void onPluggedIn(boolean pluggedIn) {
+    void setAppIdleParoleOn(boolean isAppIdleParoleOn) {
         // Flag if any app's idle state has changed
         boolean changed = false;
         synchronized (mTrackedTasks) {
-            if (mPluggedIn == pluggedIn) {
+            if (mAppIdleParoleOn == isAppIdleParoleOn) {
                 return;
             }
-            mPluggedIn = pluggedIn;
+            mAppIdleParoleOn = isAppIdleParoleOn;
             for (JobStatus task : mTrackedTasks) {
                 String packageName = task.job.getService().getPackageName();
-                final boolean appIdle = !mPluggedIn && mUsageStatsInternal.isAppIdle(packageName,
+                final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
                         task.getUserId());
                 if (DEBUG) {
-                    Slog.d(LOG_TAG, "Plugged in " + pluggedIn + ", setting idle state of "
-                            + packageName + " to " + appIdle);
+                    Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
                 }
                 if (task.appNotIdleConstraintSatisfied.get() == appIdle) {
                     task.appNotIdleConstraintSatisfied.set(!appIdle);
@@ -172,4 +122,41 @@
             mStateChangedListener.onControllerStateChanged();
         }
     }
+
+    private class AppIdleStateChangeListener
+            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
+        @Override
+        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
+            boolean changed = false;
+            synchronized (mTrackedTasks) {
+                if (mAppIdleParoleOn) {
+                    return;
+                }
+                for (JobStatus task : mTrackedTasks) {
+                    if (task.job.getService().getPackageName().equals(packageName)
+                            && task.getUserId() == userId) {
+                        if (task.appNotIdleConstraintSatisfied.get() != !idle) {
+                            if (DEBUG) {
+                                Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
+                                        + packageName + " to " + idle);
+                            }
+                            task.appNotIdleConstraintSatisfied.set(!idle);
+                            changed = true;
+                        }
+                    }
+                }
+            }
+            if (changed) {
+                mStateChangedListener.onControllerStateChanged();
+            }
+        }
+
+        @Override
+        public void onParoleStateChanged(boolean isParoleOn) {
+            if (DEBUG) {
+                Slog.d(LOG_TAG, "Parole on: " + isParoleOn);
+            }
+            setAppIdleParoleOn(isParoleOn);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index b0550d6..847bcb5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -86,7 +86,6 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.usage.UsageStatsManagerInternal;
-import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -154,7 +153,6 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.DeviceIdleController;
 import com.android.server.LocalServices;
 import com.google.android.collect.Lists;
 
@@ -182,8 +180,7 @@
  * and delivers to listeners, such as {@link ConnectivityManager}, for
  * enforcement.
  */
-public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
-        implements AppIdleStateChangeListener {
+public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     private static final String TAG = "NetworkPolicy";
     private static final boolean LOGD = false;
     private static final boolean LOGV = false;
@@ -279,6 +276,7 @@
     final SparseIntArray mUidPolicy = new SparseIntArray();
     /** Currently derived rules for each UID. */
     final SparseIntArray mUidRules = new SparseIntArray();
+    /** Set of states for the child firewall chains. True if the chain is active. */
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
 
     /**
@@ -508,7 +506,7 @@
                 WifiManager.NETWORK_STATE_CHANGED_ACTION);
         mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
 
-        mUsageStats.addAppIdleStateChangeListener(this);
+        mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
 
     }
 
@@ -2043,7 +2041,12 @@
             }
             setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
         }
-        enableFirewallChain(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
+        enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
+    }
+
+    void updateRulesForAppIdleParoleLocked() {
+        boolean enableChain = !mUsageStats.isAppIdleParoleOn();
+        enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
     }
 
     /**
@@ -2187,9 +2190,9 @@
         final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0;
         if (oldFirewallReject != firewallReject) {
             setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
-            if (mDeviceIdleMode && !firewallReject) {
-                // if we are in device idle mode, and we decide to allow this uid.  we need to punch
-                // a hole in the device idle chain.
+            if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE) && !firewallReject) {
+                // if the dozable chain is on, and we decide to allow this uid.  we need to punch
+                // a hole in the dozable chain.
                 setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false);
             }
         }
@@ -2207,15 +2210,25 @@
         }
     }
 
-    @Override
-    public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
-        try {
-            int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
-            synchronized (mRulesLock) {
-                updateRulesForUidLocked(uid);
+    private class AppIdleStateChangeListener
+            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
+
+        @Override
+        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
+            try {
+                int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
+                synchronized (mRulesLock) {
+                    updateRulesForUidLocked(uid);
+                }
+            } catch (NameNotFoundException nnfe) {
             }
-        } catch (NameNotFoundException nnfe) {
-            return;
+        }
+
+        @Override
+        public void onParoleStateChanged(boolean isParoleOn) {
+            synchronized (mRulesLock) {
+                updateRulesForAppIdleParoleLocked();
+            }
         }
     }
 
@@ -2381,12 +2394,13 @@
     /**
      * Add or remove a uid to the firewall blacklist for all network ifaces.
      */
-    private void enableFirewallChain(int chain, boolean enable) {
+    private void enableFirewallChainLocked(int chain, boolean enable) {
         if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
                 mFirewallChainStates.get(chain) == enable) {
             // All is the same, nothing to do.
             return;
         }
+        mFirewallChainStates.put(chain, enable);
         try {
             mNetworkManager.setFirewallChainEnabled(chain, enable);
         } catch (IllegalStateException e) {
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index fdb443e..87b4f8c 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -16,6 +16,8 @@
 
 package com.android.server.notification;
 
+import com.android.internal.statusbar.NotificationVisibility;
+
 public interface NotificationDelegate {
     void onSetDisabled(int status);
     void onClearAll(int callingUid, int callingPid, int userId);
@@ -30,6 +32,7 @@
     void onPanelHidden();
     void clearEffects();
     void onNotificationVisibilityChanged(
-            String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
+            NotificationVisibility[] newlyVisibleKeys,
+            NotificationVisibility[] noLongerVisibleKeys);
     void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0dcad82..4524ff8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -97,6 +97,7 @@
 import android.widget.Toast;
 
 import com.android.internal.R;
+import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
@@ -622,22 +623,24 @@
         }
 
         @Override
-        public void onNotificationVisibilityChanged(
-                String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
+        public void onNotificationVisibilityChanged(NotificationVisibility[] newlyVisibleKeys,
+                NotificationVisibility[] noLongerVisibleKeys) {
             synchronized (mNotificationList) {
-                for (String key : newlyVisibleKeys) {
-                    NotificationRecord r = mNotificationsByKey.get(key);
+                for (NotificationVisibility nv : newlyVisibleKeys) {
+                    NotificationRecord r = mNotificationsByKey.get(nv.key);
                     if (r == null) continue;
-                    r.setVisibility(true);
+                    r.setVisibility(true, nv.rank);
+                    nv.recycle();
                 }
                 // Note that we might receive this event after notifications
                 // have already left the system, e.g. after dismissing from the
                 // shade. Hence not finding notifications in
                 // mNotificationsByKey is not an exceptional condition.
-                for (String key : noLongerVisibleKeys) {
-                    NotificationRecord r = mNotificationsByKey.get(key);
+                for (NotificationVisibility nv : noLongerVisibleKeys) {
+                    NotificationRecord r = mNotificationsByKey.get(nv.key);
                     if (r == null) continue;
-                    r.setVisibility(false);
+                    r.setVisibility(false, nv.rank);
+                    nv.recycle();
                 }
             }
         }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index c4773ca..b7aea9d 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -314,13 +314,15 @@
     /**
      * Set the visibility of the notification.
      */
-    public void setVisibility(boolean visible) {
+    public void setVisibility(boolean visible, int rank) {
         final long now = System.currentTimeMillis();
         mVisibleSinceMs = visible ? now : mVisibleSinceMs;
         stats.onVisibilityChanged(visible);
         EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
                 (int) (now - mCreationTimeMs),
-                (int) (now - mUpdateTimeMs));
+                (int) (now - mUpdateTimeMs),
+                0, // exposure time
+                rank);
     }
 
     /**
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 2d5c199..2f0cc0f 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -16,11 +16,13 @@
 
 package com.android.server.notification;
 
+import android.app.Notification;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -57,8 +59,8 @@
 
     private static final boolean DEBUG = false;
     public static final int TEN_SECONDS = 1000 * 10;
-    public static final int ONE_HOUR = 1000 * 60 * 60;
-    private static final long EMIT_PERIOD = DEBUG ? TEN_SECONDS : ONE_HOUR;
+    public static final int FOUR_HOURS = 1000 * 60 * 60 * 4;
+    private static final long EMIT_PERIOD = DEBUG ? TEN_SECONDS : FOUR_HOURS;
 
     // Guarded by synchronized(this).
     private final Map<String, AggregatedStats> mStats = new HashMap<>();
@@ -98,6 +100,7 @@
         AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
         for (AggregatedStats stats : aggregatedStatsArray) {
             stats.numPostedByApp++;
+            stats.countApiUse(notification);
         }
         releaseAggregatedStatsLocked(aggregatedStatsArray);
         if (ENABLE_SQLITE_LOG) {
@@ -113,6 +116,7 @@
         AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
         for (AggregatedStats stats : aggregatedStatsArray) {
             stats.numUpdatedByApp++;
+            stats.countApiUse(notification);
         }
         releaseAggregatedStatsLocked(aggregatedStatsArray);
     }
@@ -246,6 +250,7 @@
 
         private final Context mContext;
         public final String key;
+        private AggregatedStats mPrevious;
 
         // ---- Updated as the respective events occur.
         public int numPostedByApp;
@@ -256,14 +261,103 @@
         public int numWithStaredPeople;
         public int numWithValidPeople;
         public int numBlocked;
-
-        private AggregatedStats mPrevious;
+        public int numWithActions;
+        public int numPrivate;
+        public int numSecret;
+        public int numPriorityMax;
+        public int numPriorityHigh;
+        public int numPriorityLow;
+        public int numPriorityMin;
+        public int numWithBigText;
+        public int numWithBigPicture;
+        public int numForegroundService;
+        public int numOngoing;
+        public int numAutoCancel;
+        public int numWithLargeIcon;
+        public int numWithInbox;
+        public int numWithMediaSession;
+        public int numWithTitle;
+        public int numWithText;
+        public int numWithSubText;
+        public int numWithInfoText;
+        public int numInterrupt;
 
         public AggregatedStats(Context context, String key) {
             this.key = key;
             mContext = context;
         }
 
+        public void countApiUse(NotificationRecord record) {
+            final Notification n = record.getNotification();
+            if (n.actions != null) {
+                numWithActions++;
+            }
+
+            if ((n.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+                numForegroundService++;
+            }
+
+            if ((n.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
+                numOngoing++;
+            }
+
+            if ((n.flags & Notification.FLAG_AUTO_CANCEL) != 0) {
+                numAutoCancel++;
+            }
+
+            if ((n.defaults & Notification.DEFAULT_SOUND) != 0 ||
+                    (n.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
+                    n.sound != null || n.vibrate != null) {
+                numInterrupt++;
+            }
+
+            switch (n.visibility) {
+                case Notification.VISIBILITY_PRIVATE:
+                    numPrivate++;
+                    break;
+                case Notification.VISIBILITY_SECRET:
+                    numSecret++;
+                    break;
+            }
+
+            switch (n.priority) {
+                case Notification.PRIORITY_MAX:
+                    numPriorityMax++;
+                    break;
+                case Notification.PRIORITY_HIGH:
+                    numPriorityHigh++;
+                    break;
+                case Notification.PRIORITY_LOW:
+                    numPriorityLow++;
+                    break;
+                case Notification.PRIORITY_MIN:
+                    numPriorityMin++;
+                    break;
+            }
+
+            for (String Key : n.extras.keySet()) {
+                if (Notification.EXTRA_BIG_TEXT.equals(key)) {
+                    numWithBigText++;
+                } else if (Notification.EXTRA_PICTURE.equals(key)) {
+                    numWithBigPicture++;
+                } else if (Notification.EXTRA_LARGE_ICON.equals(key)) {
+                    numWithLargeIcon++;
+                } else if (Notification.EXTRA_TEXT_LINES.equals(key)) {
+                    numWithInbox++;
+                } else if (Notification.EXTRA_MEDIA_SESSION.equals(key)) {
+                    numWithMediaSession++;
+                } else if (Notification.EXTRA_TITLE.equals(key)) {
+                    numWithTitle++;
+                } else if (Notification.EXTRA_TEXT.equals(key)) {
+                    numWithText++;
+                } else if (Notification.EXTRA_SUB_TEXT.equals(key)) {
+                    numWithSubText++;
+                } else if (Notification.EXTRA_INFO_TEXT.equals(key)) {
+                    numWithInfoText++;
+                }
+            }
+        }
+
         public void emit() {
             if (mPrevious == null) {
                 mPrevious = new AggregatedStats(null, key);
@@ -277,6 +371,26 @@
             maybeCount("people_cache_hit", (numPeopleCacheHit - mPrevious.numPeopleCacheHit));
             maybeCount("people_cache_miss", (numPeopleCacheMiss - mPrevious.numPeopleCacheMiss));
             maybeCount("note_blocked", (numBlocked - mPrevious.numBlocked));
+            maybeCount("note_with_actions", (numWithActions - mPrevious.numWithActions));
+            maybeCount("note_private", (numPrivate - mPrevious.numPrivate));
+            maybeCount("note_secret", (numSecret - mPrevious.numSecret));
+            maybeCount("note_prio_max", (numPriorityMax - mPrevious.numPriorityMax));
+            maybeCount("note_prio_high", (numPriorityHigh - mPrevious.numPriorityHigh));
+            maybeCount("note_prio_low", (numPriorityLow - mPrevious.numPriorityLow));
+            maybeCount("note_prio_min", (numPriorityMin - mPrevious.numPriorityMin));
+            maybeCount("note_interupt", (numInterrupt - mPrevious.numInterrupt));
+            maybeCount("note_big_text", (numWithBigText - mPrevious.numWithBigText));
+            maybeCount("note_big_pic", (numWithBigPicture - mPrevious.numWithBigPicture));
+            maybeCount("note_fg", (numForegroundService - mPrevious.numForegroundService));
+            maybeCount("note_ongoing", (numOngoing - mPrevious.numOngoing));
+            maybeCount("note_auto", (numAutoCancel - mPrevious.numAutoCancel));
+            maybeCount("note_large_icon", (numWithLargeIcon - mPrevious.numWithLargeIcon));
+            maybeCount("note_inbox", (numWithInbox - mPrevious.numWithInbox));
+            maybeCount("note_media", (numWithMediaSession - mPrevious.numWithMediaSession));
+            maybeCount("note_title", (numWithTitle - mPrevious.numWithTitle));
+            maybeCount("note_text", (numWithText - mPrevious.numWithText));
+            maybeCount("note_sub_text", (numWithSubText - mPrevious.numWithSubText));
+            maybeCount("note_info_text", (numWithInfoText - mPrevious.numWithInfoText));
 
             mPrevious.numPostedByApp = numPostedByApp;
             mPrevious.numUpdatedByApp = numUpdatedByApp;
@@ -286,6 +400,26 @@
             mPrevious.numWithStaredPeople = numWithStaredPeople;
             mPrevious.numWithValidPeople = numWithValidPeople;
             mPrevious.numBlocked = numBlocked;
+            mPrevious.numWithActions = numWithActions;
+            mPrevious.numPrivate = numPrivate;
+            mPrevious.numSecret = numSecret;
+            mPrevious.numPriorityMax = numPriorityMax;
+            mPrevious.numPriorityHigh = numPriorityHigh;
+            mPrevious.numPriorityLow = numPriorityLow;
+            mPrevious.numPriorityMin = numPriorityMin;
+            mPrevious.numInterrupt = numInterrupt;
+            mPrevious.numWithBigText = numWithBigText;
+            mPrevious.numWithBigPicture = numWithBigPicture;
+            mPrevious.numForegroundService = numForegroundService;
+            mPrevious.numOngoing = numOngoing;
+            mPrevious.numAutoCancel = numAutoCancel;
+            mPrevious.numWithLargeIcon = numWithLargeIcon;
+            mPrevious.numWithInbox = numWithInbox;
+            mPrevious.numWithMediaSession = numWithMediaSession;
+            mPrevious.numWithTitle = numWithTitle;
+            mPrevious.numWithText = numWithText;
+            mPrevious.numWithSubText = numWithSubText;
+            mPrevious.numWithInfoText = numWithInfoText;
         }
 
         void maybeCount(String name, int value) {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index fe3103b..3ea384c 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -45,7 +45,7 @@
  * have phone related permission by default.
  */
 final class DefaultPermissionGrantPolicy {
-    private static final String TAG = "DefaultPermissionGrantPolicy";
+    private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -106,7 +106,7 @@
 
     private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>();
     static {
-//        STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+        STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
         STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
     }
 
@@ -133,6 +133,7 @@
     private PackagesProvider mImePackagesProvider;
     private PackagesProvider mLocationPackagesProvider;
     private PackagesProvider mVoiceInteractionPackagesProvider;
+    private PackagesProvider mCarrierAppPackagesProvider;
 
     public DefaultPermissionGrantPolicy(PackageManagerService service) {
         mService = service;
@@ -150,6 +151,10 @@
         mVoiceInteractionPackagesProvider = provider;
     }
 
+    public void setCarrierAppPackagesProviderLPw(PackagesProvider provider) {
+        mCarrierAppPackagesProvider = provider;
+    }
+
     public void grantDefaultPermissions(int userId) {
         grantPermissionsToSysComponentsAndPrivApps(userId);
         grantDefaultSystemHandlerPermissions(userId);
@@ -193,11 +198,13 @@
         final PackagesProvider imePackagesProvider;
         final PackagesProvider locationPackagesProvider;
         final PackagesProvider voiceInteractionPackagesProvider;
+        final PackagesProvider carrierAppPackagesProvider;
 
         synchronized (mService.mPackages) {
             imePackagesProvider = mImePackagesProvider;
             locationPackagesProvider = mLocationPackagesProvider;
             voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
+            carrierAppPackagesProvider = mCarrierAppPackagesProvider;
         }
 
         String[] imePackageNames = (imePackagesProvider != null)
@@ -206,6 +213,8 @@
                 ? voiceInteractionPackagesProvider.getPackages(userId) : null;
         String[] locationPackageNames = (locationPackagesProvider != null)
                 ? locationPackagesProvider.getPackages(userId) : null;
+        String[] carrierAppPackageNames = (carrierAppPackagesProvider != null)
+                ? carrierAppPackagesProvider.getPackages(userId) : null;
 
         synchronized (mService.mPackages) {
             // Installers
@@ -382,6 +391,18 @@
                     }
                 }
             }
+
+            // Carrier apps
+            if (carrierAppPackageNames != null) {
+                for (String packageName : carrierAppPackageNames) {
+                    PackageParser.Package carrierPackage = getSystemPackageLPr(packageName);
+                    if (carrierPackage != null
+                            && doesPackageSupportRuntimePermissions(carrierPackage)) {
+                        grantRuntimePermissionsLPw(carrierPackage, PHONE_PERMISSIONS, userId);
+                        grantRuntimePermissionsLPw(carrierPackage, LOCATION_PERMISSIONS, userId);
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 080a37a..2da24cc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -100,6 +100,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IPackagesProvider;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
@@ -254,14 +255,14 @@
 
 /**
  * Keep track of all those .apks everywhere.
- * 
+ *
  * This is very central to the platform's security; please run the unit
  * tests whenever making modifications here:
- * 
+ *
 mmm frameworks/base/tests/AndroidTests
 adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
 adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
- * 
+ *
  * {@hide}
  */
 public class PackageManagerService extends IPackageManager.Stub {
@@ -509,7 +510,7 @@
     // Packages whose data we have transfered into another package, thus
     // should no longer exist.
     final ArraySet<String> mTransferedPackages = new ArraySet<String>();
-    
+
     // Broadcast actions that are only available to the system.
     final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>();
 
@@ -1092,7 +1093,7 @@
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             }
         }
-        
+
         void doHandleMessage(Message msg) {
             switch (msg.what) {
                 case INIT_COPY: {
@@ -2502,7 +2503,7 @@
         }
         return out;
     }
-    
+
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
         String[] out = new String[names.length];
@@ -2572,7 +2573,7 @@
         pi.protectionLevel = bp.protectionLevel;
         return pi;
     }
-    
+
     @Override
     public PermissionInfo getPermissionInfo(String name, int flags) {
         // reader
@@ -3052,7 +3053,7 @@
         }
         return s1.equals(s2);
     }
-    
+
     static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
         if (pi1.icon != pi2.icon) return false;
         if (pi1.logo != pi2.logo) return false;
@@ -3354,11 +3355,8 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
                 "updatePermissionFlags");
 
-        // Only the system can change policy and system fixed flags.
+        // Only the system can change system fixed flags.
         if (getCallingUid() != Process.SYSTEM_UID) {
-            flagMask &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
-
             flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
             flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
         }
@@ -3387,18 +3385,63 @@
                 return;
             }
 
+            boolean hadState = permissionsState.getRuntimePermissionState(name, userId) != null;
+
             if (permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues)) {
                 // Install and runtime permissions are stored in different places,
                 // so figure out what permission changed and persist the change.
                 if (permissionsState.getInstallPermissionState(name) != null) {
                     scheduleWriteSettingsLocked();
-                } else if (permissionsState.getRuntimePermissionState(name, userId) != null) {
+                } else if (permissionsState.getRuntimePermissionState(name, userId) != null
+                        || hadState) {
                     mSettings.writeRuntimePermissionsForUserLPr(userId, false);
                 }
             }
         }
     }
 
+    /**
+     * Update the permission flags for all packages and runtime permissions of a user in order
+     * to allow device or profile owner to remove POLICY_FIXED.
+     */
+    @Override
+    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
+        if (!sUserManager.exists(userId)) {
+            return;
+        }
+
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+                "updatePermissionFlagsForAllApps");
+
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
+                "updatePermissionFlagsForAllApps");
+
+        // Only the system can change system fixed flags.
+        if (getCallingUid() != Process.SYSTEM_UID) {
+            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+        }
+
+        synchronized (mPackages) {
+            boolean changed = false;
+            final int packageCount = mPackages.size();
+            for (int pkgIndex = 0; pkgIndex < packageCount; pkgIndex++) {
+                final PackageParser.Package pkg = mPackages.valueAt(pkgIndex);
+                SettingBase sb = (SettingBase) pkg.mExtras;
+                if (sb == null) {
+                    continue;
+                }
+                PermissionsState permissionsState = sb.getPermissionsState();
+                changed |= permissionsState.updatePermissionFlagsForAllPermissions(
+                        userId, flagMask, flagValues);
+            }
+            if (changed) {
+                mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+            }
+        }
+    }
+
     @Override
     public boolean shouldShowRequestPermissionRationale(String permissionName,
             String packageName, int userId) {
@@ -4172,7 +4215,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -4727,7 +4770,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -4778,7 +4821,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -6205,7 +6248,7 @@
                                 + "): packages=" + suid.packages);
                 }
             }
-            
+
             // Check if we are renaming from an original package name.
             PackageSetting origPackage = null;
             String realName = null;
@@ -6225,7 +6268,7 @@
                         // it is not already done.
                         pkg.setPackageName(renamed);
                     }
-                    
+
                 } else {
                     for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
                         if ((origPackage = mSettings.peekPackageLPr(
@@ -6255,7 +6298,7 @@
                     }
                 }
             }
-            
+
             if (mTransferedPackages.contains(pkg.packageName)) {
                 Slog.w(TAG, "Package " + pkg.packageName
                         + " was transferred to another, but its .apk remains");
@@ -6280,24 +6323,24 @@
                 // looking up the package under its new name, so getPackageLP
                 // can take care of fiddling things correctly.
                 pkg.setPackageName(origPackage.name);
-                
+
                 // File a report about this.
                 String msg = "New package " + pkgSetting.realName
                         + " renamed to replace old package " + pkgSetting.name;
                 reportSettingsProblem(Log.WARN, msg);
-                
+
                 // Make a note of it.
                 mTransferedPackages.add(origPackage.name);
-                
+
                 // No longer need to retain this.
                 pkgSetting.origPackage = null;
             }
-            
+
             if (realName != null) {
                 // Make a note of it.
                 mTransferedPackages.add(pkg.packageName);
             }
-            
+
             if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
@@ -6413,7 +6456,7 @@
         }
 
         final String pkgName = pkg.packageName;
-        
+
         final long scanFileTime = scanFile.lastModified();
         final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
         pkg.applicationInfo.processName = fixProcessName(
@@ -8333,7 +8376,7 @@
                 PackageParser.ActivityIntentInfo info) {
             return packageName.equals(info.activity.owner.packageName);
         }
-        
+
         @Override
         protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
                 int match, int userId) {
@@ -8556,7 +8599,7 @@
                 PackageParser.ServiceIntentInfo info) {
             return packageName.equals(info.service.owner.packageName);
         }
-        
+
         @Override
         protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
                 int match, int userId) {
@@ -14112,7 +14155,7 @@
         boolean checkin = false;
 
         String packageName = null;
-        
+
         int opti = 0;
         while (opti < args.length) {
             String opt = args[opti];
@@ -15758,4 +15801,55 @@
             }
         }
     }
+
+    @Override
+    public void grantDefaultPermissions(final int userId) {
+        enforceSystemOrPhoneCaller("grantDefaultPermissions");
+        long token = Binder.clearCallingIdentity();
+        try {
+            // We cannot grant the default permissions with a lock held as
+            // we query providers from other components for default handlers
+            // such as enabled IMEs, etc.
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mDefaultPermissionPolicy.grantDefaultPermissions(userId);
+                }
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void setCarrierAppPackagesProvider(final IPackagesProvider provider) {
+        enforceSystemOrPhoneCaller("setCarrierAppPackagesProvider");
+        long token = Binder.clearCallingIdentity();
+        try {
+            PackageManagerInternal.PackagesProvider wrapper =
+                    new PackageManagerInternal.PackagesProvider() {
+                @Override
+                public String[] getPackages(int userId) {
+                    try {
+                        return provider.getPackages(userId);
+                    } catch (RemoteException e) {
+                        return null;
+                    }
+                }
+            };
+            synchronized (mPackages) {
+                mDefaultPermissionPolicy.setCarrierAppPackagesProviderLPw(wrapper);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private static void enforceSystemOrPhoneCaller(String tag) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "Cannot call " + tag + " from UID " + callingUid);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java
index ad662be..04beafd 100644
--- a/services/core/java/com/android/server/pm/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/PermissionsState.java
@@ -344,6 +344,22 @@
         return permissionData.updateFlags(userId, flagMask, flagValues);
     }
 
+    public boolean updatePermissionFlagsForAllPermissions(
+            int userId, int flagMask, int flagValues) {
+        enforceValidUserId(userId);
+
+        if (mPermissions == null) {
+            return false;
+        }
+        boolean changed = false;
+        final int permissionCount = mPermissions.size();
+        for (int i = 0; i < permissionCount; i++) {
+            PermissionData permissionData = mPermissions.valueAt(i);
+            changed |= permissionData.updateFlags(userId, flagMask, flagValues);
+        }
+        return changed;
+    }
+
     /**
      * Compute the Linux gids for a given device user from the permissions
      * granted to this user. Note that these are computed to avoid additional
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index a754379..7640837 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -29,6 +29,7 @@
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.server.LocalServices;
@@ -660,7 +661,8 @@
 
     @Override
     public void onNotificationVisibilityChanged(
-            String[] newlyVisibleKeys, String[] noLongerVisibleKeys) throws RemoteException {
+            NotificationVisibility[] newlyVisibleKeys, NotificationVisibility[] noLongerVisibleKeys)
+            throws RemoteException {
         enforceStatusBarService();
         long identity = Binder.clearCallingIdentity();
         try {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ace5997..b285b66 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2671,6 +2671,16 @@
 
         synchronized(mWindowMap) {
             mScreenCaptureDisabled.put(userId, disabled);
+            // Update secure surface for all windows belonging to this user.
+            for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+                WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
+                for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                    final WindowState win = windows.get(winNdx);
+                    if (win.mHasSurface && userId == UserHandle.getUserId(win.mOwnerUid)) {
+                        win.mWinAnimator.setSecureLocked(disabled);
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index f1331e9..d818519 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -658,6 +658,11 @@
         }
 
         @Override
+        public void setSecure(boolean isSecure) {
+            super.setSecure(isSecure);
+        }
+
+        @Override
         public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
             if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
@@ -1663,6 +1668,22 @@
         }
     }
 
+    void setSecureLocked(boolean isSecure) {
+        if (mSurfaceControl == null) {
+            return;
+        }
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked");
+        SurfaceControl.openTransaction();
+        try {
+            if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isSecure=" + isSecure,
+                    null);
+            mSurfaceControl.setSecure(isSecure);
+        } finally {
+            SurfaceControl.closeTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked");
+        }
+    }
+
     // This must be called while inside a transaction.
     boolean performShowLocked() {
         if (mWin.isHiddenFromUserLocked()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 416ea73..e44a7ab87 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -246,6 +246,7 @@
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_SLEEP_POLICY);
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN);
     }
 
     // Keyguard features that when set of a profile will affect the profiles
@@ -4216,11 +4217,15 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 clearUserRestrictions(new UserHandle(UserHandle.USER_OWNER));
+                AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
+                        PackageManager.FLAG_PERMISSION_POLICY_FIXED,
+                        0, UserHandle.USER_OWNER);
                 if (mDeviceOwner != null) {
                     mDeviceOwner.clearDeviceOwner();
                     mDeviceOwner.writeOwnerFile();
                     updateDeviceOwnerLocked();
                 }
+            } catch (RemoteException re) {
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -4387,10 +4392,14 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 clearUserRestrictions(callingUser);
+                AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
+                        PackageManager.FLAG_PERMISSION_POLICY_FIXED,
+                        0, callingUser.getIdentifier());
                 if (mDeviceOwner != null) {
                     mDeviceOwner.removeProfileOwner(userId);
                     mDeviceOwner.writeOwnerFile();
                 }
+            } catch (RemoteException re) {
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -6389,21 +6398,27 @@
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             long ident = Binder.clearCallingIdentity();
             try {
-                PackageManager packageManager = mContext.getPackageManager();
+                final ApplicationInfo ai = AppGlobals.getPackageManager()
+                        .getApplicationInfo(packageName, 0, user.getIdentifier());
+                final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
+                if (targetSdkVersion < android.os.Build.VERSION_CODES.MNC) {
+                    return false;
+                }
+                final PackageManager packageManager = mContext.getPackageManager();
                 switch (grantState) {
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
+                        packageManager.grantRuntimePermission(packageName, permission, user);
                         packageManager.updatePermissionFlags(permission, packageName,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
-                        packageManager.grantRuntimePermission(packageName, permission, user);
                     } break;
 
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
+                        packageManager.revokeRuntimePermission(packageName,
+                                permission, user);
                         packageManager.updatePermissionFlags(permission, packageName,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
-                        packageManager.revokeRuntimePermission(packageName,
-                                permission, user);
                     } break;
 
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT: {
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 712db09..fb8a5bb 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -34,6 +34,7 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -792,6 +793,30 @@
         handlerThread.quit();
     }
 
+    @LargeTest
+    public void testNoMutableNetworkRequests() throws Exception {
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
+        NetworkRequest.Builder builder = new NetworkRequest.Builder();
+        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+        try {
+            mCm.requestNetwork(builder.build(), new NetworkCallback());
+            fail();
+        } catch (IllegalArgumentException expected) {}
+        try {
+            mCm.requestNetwork(builder.build(), pendingIntent);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+        builder = new NetworkRequest.Builder();
+        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+        try {
+            mCm.requestNetwork(builder.build(), new NetworkCallback());
+            fail();
+        } catch (IllegalArgumentException expected) {}
+        try {
+            mCm.requestNetwork(builder.build(), pendingIntent);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
 
 //    @Override
 //    public void tearDown() throws Exception {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 490236e..c49a5f9 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -119,6 +119,7 @@
     static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
     static final int MSG_PAROLE_END_TIMEOUT = 7;
     static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
+    static final int MSG_PAROLE_STATE_CHANGED = 9;
 
     private final Object mLock = new Object();
     Handler mHandler;
@@ -313,7 +314,7 @@
                     mLastAppIdleParoledTime = checkAndGetTimeLocked();
                     postNextParoleTimeout();
                 }
-                postCheckIdleStates(UserHandle.USER_ALL);
+                postParoleStateChanged();
             }
         }
     }
@@ -338,6 +339,12 @@
         mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
     }
 
+    private void postParoleStateChanged() {
+        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
+        mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
+        mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
+    }
+
     void postCheckIdleStates(int userId) {
         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
     }
@@ -756,6 +763,13 @@
         }
     }
 
+    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long timeNow) {
+        if (mAppIdleParoled) {
+            return false;
+        }
+        return isAppIdleFiltered(packageName, userId, timeNow);
+    }
+
     boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
         final UserUsageStatsService userService;
         final long screenOnTime;
@@ -782,13 +796,6 @@
         if (!mAppIdleEnabled) {
             return false;
         }
-        synchronized (mLock) {
-            // Temporary exemption, probably due to device charging or occasional allowance to
-            // be allowed to sync, etc.
-            if (mAppIdleParoled) {
-                return false;
-            }
-        }
         if (packageName.equals("android")) return false;
         try {
             if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) {
@@ -846,6 +853,12 @@
         }
     }
 
+    void informParoleStateChanged() {
+        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
+            listener.onParoleStateChanged(mAppIdleParoled);
+        }
+    }
+
     private static boolean validRange(long currentTime, long beginTime, long endTime) {
         return beginTime <= currentTime && beginTime < endTime;
     }
@@ -975,6 +988,11 @@
                     args.recycle();
                     break;
 
+                case MSG_PAROLE_STATE_CHANGED:
+                    if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled);
+                    informParoleStateChanged();
+                    break;
+
                 default:
                     super.handleMessage(msg);
                     break;
@@ -1126,7 +1144,7 @@
             }
             final long token = Binder.clearCallingIdentity();
             try {
-                return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
+                return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1251,6 +1269,11 @@
         }
 
         @Override
+        public boolean isAppIdleParoleOn() {
+            return mAppIdleParoled;
+        }
+
+        @Override
         public void prepareShutdown() {
             // This method *WILL* do IO work, but we must block until it is finished or else
             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
@@ -1261,6 +1284,7 @@
         @Override
         public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
             UsageStatsService.this.addListener(listener);
+            listener.onParoleStateChanged(isAppIdleParoleOn());
         }
 
         @Override
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
index 8a72341..439ace8 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
@@ -17,7 +17,7 @@
 package com.android.test.voiceinteraction;
 
 import android.annotation.Nullable;
-import android.app.AssistStructure;
+import android.app.assist.AssistStructure;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 3090a11..90a781c 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -18,8 +18,8 @@
 
 import android.app.ActivityManager;
 import android.app.VoiceInteractor;
-import android.app.AssistContent;
-import android.app.AssistStructure;
+import android.app.assist.AssistContent;
+import android.app.assist.AssistStructure;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -123,34 +123,8 @@
     }
 
     public void onHandleAssist(Bundle assistBundle) {
-        boolean hasStructure = false;
-        if (assistBundle != null) {
-            Bundle assistContext = assistBundle.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
-            if (assistContext != null) {
-                mAssistStructure = AssistStructure.getAssistStructure(assistContext);
-                if (mAssistStructure != null) {
-                    if (mAssistVisualizer != null) {
-                        mAssistVisualizer.setAssistStructure(mAssistStructure);
-                        hasStructure = true;
-                    }
-                }
-                AssistContent content = AssistContent.getAssistContent(assistContext);
-                if (content != null) {
-                    Log.i(TAG, "Assist intent: " + content.getIntent());
-                    Log.i(TAG, "Assist clipdata: " + content.getClipData());
-                }
-            }
-            Uri referrer = assistBundle.getParcelable(Intent.EXTRA_REFERRER);
-            if (referrer != null) {
-                Log.i(TAG, "Referrer: " + referrer);
-            }
-        }
-        if (!hasStructure && mAssistVisualizer != null) {
-            mAssistVisualizer.clearAssistData();
-        }
     }
 
-    /*
     @Override
     public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) {
         mAssistStructure = structure;
@@ -158,13 +132,22 @@
             if (mAssistVisualizer != null) {
                 mAssistVisualizer.setAssistStructure(mAssistStructure);
             }
+        } else {
+            if (mAssistVisualizer != null) {
+                mAssistVisualizer.clearAssistData();
+            }
         }
         if (content != null) {
             Log.i(TAG, "Assist intent: " + content.getIntent());
             Log.i(TAG, "Assist clipdata: " + content.getClipData());
         }
+        if (data != null) {
+            Uri referrer = data.getParcelable(Intent.EXTRA_REFERRER);
+            if (referrer != null) {
+                Log.i(TAG, "Referrer: " + referrer);
+            }
+        }
     }
-    */
 
     @Override
     public void onHandleScreenshot(Bitmap screenshot) {
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index c038414..943c647 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.test.voiceinteraction;
 
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.VoiceInteractor;
 import android.content.ComponentName;
@@ -111,38 +112,10 @@
     @Override
     public void onClick(View v) {
         if (v == mAbortButton) {
-            VoiceInteractor.AbortVoiceRequest req = new VoiceInteractor.AbortVoiceRequest(
-                    new VoiceInteractor.Prompt("Dammit, we suck :("), null) {
-                @Override
-                public void onCancel() {
-                    Log.i(TAG, "Canceled!");
-                    mLog.append("Canceled abort\n");
-                }
-
-                @Override
-                public void onAbortResult(Bundle result) {
-                    Log.i(TAG, "Abort result: result=" + result);
-                    mLog.append("Abort: result=" + result + "\n");
-                    getActivity().finish();
-                }
-            };
+            VoiceInteractor.AbortVoiceRequest req = new TestAbortVoice();
             mInteractor.submitRequest(req, REQUEST_ABORT);
         } else if (v == mCompleteButton) {
-            VoiceInteractor.CompleteVoiceRequest req = new VoiceInteractor.CompleteVoiceRequest(
-                    new VoiceInteractor.Prompt("Woohoo, completed!"), null) {
-                @Override
-                public void onCancel() {
-                    Log.i(TAG, "Canceled!");
-                    mLog.append("Canceled complete\n");
-                }
-
-                @Override
-                public void onCompleteResult(Bundle result) {
-                    Log.i(TAG, "Complete result: result=" + result);
-                    mLog.append("Complete: result=" + result + "\n");
-                    getActivity().finish();
-                }
-            };
+            VoiceInteractor.CompleteVoiceRequest req = new TestCompleteVoice();
             mInteractor.submitRequest(req, REQUEST_COMPLETE);
         } else if (v == mPickButton) {
             VoiceInteractor.PickOptionRequest.Option[] options =
@@ -152,36 +125,7 @@
             options[2] = new VoiceInteractor.PickOptionRequest.Option("Three");
             options[3] = new VoiceInteractor.PickOptionRequest.Option("Four");
             options[4] = new VoiceInteractor.PickOptionRequest.Option("Five");
-            VoiceInteractor.PickOptionRequest req = new VoiceInteractor.PickOptionRequest(
-                    new VoiceInteractor.Prompt("Need to pick something"), options, null) {
-                @Override
-                public void onCancel() {
-                    Log.i(TAG, "Canceled!");
-                    mLog.append("Canceled pick\n");
-                }
-
-                @Override
-                public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
-                    Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
-                            + " result=" + result);
-                    StringBuilder sb = new StringBuilder();
-                    if (finished) {
-                        sb.append("Pick final result: ");
-                    } else {
-                        sb.append("Pick intermediate result: ");
-                    }
-                    for (int i=0; i<selections.length; i++) {
-                        if (i >= 1) {
-                            sb.append(", ");
-                        }
-                        sb.append(selections[i].getLabel());
-                    }
-                    mLog.append(sb.toString());
-                    if (finished) {
-                        getActivity().finish();
-                    }
-                }
-            };
+            VoiceInteractor.PickOptionRequest req = new TestPickOption(options);
             mInteractor.submitRequest(req, REQUEST_PICK);
         } else if (v == mJumpOutButton) {
             Log.i(TAG, "Jump out");
@@ -200,4 +144,66 @@
     public void onDestroy() {
         super.onDestroy();
     }
+
+    static class TestAbortVoice extends VoiceInteractor.AbortVoiceRequest {
+        public TestAbortVoice() {
+            super(new VoiceInteractor.Prompt("Dammit, we suck :("), null);
+        }
+        @Override public void onCancel() {
+            Log.i(TAG, "Canceled!");
+            ((TestInteractionActivity)getActivity()).mLog.append("Canceled abort\n");
+        }
+        @Override public void onAbortResult(Bundle result) {
+            Log.i(TAG, "Abort result: result=" + result);
+            ((TestInteractionActivity)getActivity()).mLog.append("Abort: result=" + result + "\n");
+            getActivity().finish();
+        }
+    }
+
+    static class TestCompleteVoice extends VoiceInteractor.CompleteVoiceRequest {
+        public TestCompleteVoice() {
+            super(new VoiceInteractor.Prompt("Woohoo, completed!"), null);
+        }
+        @Override public void onCancel() {
+            Log.i(TAG, "Canceled!");
+            ((TestInteractionActivity)getActivity()).mLog.append("Canceled complete\n");
+        }
+        @Override public void onCompleteResult(Bundle result) {
+            Log.i(TAG, "Complete result: result=" + result);
+            ((TestInteractionActivity)getActivity()).mLog.append("Complete: result="
+                    + result + "\n");
+            getActivity().finish();
+        }
+    }
+
+    static class TestPickOption extends VoiceInteractor.PickOptionRequest {
+        public TestPickOption(Option[] options) {
+            super(new VoiceInteractor.Prompt("Need to pick something"), options, null);
+        }
+        @Override public void onCancel() {
+            Log.i(TAG, "Canceled!");
+            ((TestInteractionActivity)getActivity()).mLog.append("Canceled pick\n");
+        }
+        @Override
+        public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
+            Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
+                    + " result=" + result);
+            StringBuilder sb = new StringBuilder();
+            if (finished) {
+                sb.append("Pick final result: ");
+            } else {
+                sb.append("Pick intermediate result: ");
+            }
+            for (int i=0; i<selections.length; i++) {
+                if (i >= 1) {
+                    sb.append(", ");
+                }
+                sb.append(selections[i].getLabel());
+            }
+            ((TestInteractionActivity)getActivity()).mLog.append(sb.toString());
+            if (finished) {
+                getActivity().finish();
+            }
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 5dc70bd..fc6a3de 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
 /**
  * Describes information about a detected access point. In addition
@@ -80,27 +81,30 @@
     public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
 
    /**
-    * AP Channel bandwidth
+    * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
+    * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}
+    * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}.
     */
     public int channelWidth;
 
     /**
      * Not used if the AP bandwidth is 20 MHz
-     * If the AP use 40, 80 or 160 MHz, this is the center frequency
-     * if the AP use 80 + 80 MHz, this is the center frequency of the first segment
+     * If the AP use 40, 80 or 160 MHz, this is the center frequency (in MHz)
+     * if the AP use 80 + 80 MHz, this is the center frequency of the first segment (in MHz)
      */
     public int centerFreq0;
 
     /**
      * Only used if the AP bandwidth is 80 + 80 MHz
-     * if the AP use 80 + 80 MHz, this is the center frequency of the second segment
+     * if the AP use 80 + 80 MHz, this is the center frequency of the second segment (in MHz)
      */
     public int centerFreq1;
 
     /**
-     * Whether the AP support 802.11mc Responder
+     * @deprecated use is80211mcResponder() instead
+     * @hide
      */
-   public boolean is80211McRTTResponder;
+    public boolean is80211McRTTResponder;
 
     /**
      * timestamp in microseconds (since boot) when
@@ -123,7 +127,7 @@
     /**
      * @hide
      * Update RSSI of the scan result
-     * @param previousRSSI
+     * @param previousRssi
      * @param previousSeen
      * @param maxAge
      */
@@ -206,26 +210,56 @@
     public int distanceCm;
 
     /**
-     * The standard deviation of the distance to the AP, if available.
+     * The standard deviation of the distance to the access point, if available.
      * Else {@link UNSPECIFIED}.
      * {@hide}
      */
     public int distanceSdCm;
 
-    /**
-     * Indicates if the scan result represents a passpoint AP
-     */
-    public boolean passpointNetwork;
+    public static final long FLAG_PASSPOINT_NETWORK               = 0x0000000000000001;
+    public static final long FLAG_80211mc_RESPONDER               = 0x0000000000000002;
 
     /**
-     * Indicates if venue name
+     * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}.
      */
-    public String venueName;
+    public long flags;
 
     /**
-     * Indicates operator name
+     * sets a flag in {@link #flags} field
+     * @param flag flag to set
+     * @hide
      */
-    public String operatorFriendlyName;
+    public void setFlag(long flag) {
+        flags |= flag;
+    }
+
+    /**
+     * clears a flag in {@link #flags} field
+     * @param flag flag to set
+     * @hide
+     */
+    public void clearFlag(long flag) {
+        flags &= ~flag;
+    }
+
+    public boolean is80211mcResponder() {
+        return (flags & FLAG_80211mc_RESPONDER) != 0;
+    }
+
+    public boolean isPasspointNetwork() {
+        return (flags & FLAG_PASSPOINT_NETWORK) != 0;
+    }
+
+    /**
+     * Indicates venue name (such as 'San Francisco Airport') published by access point; only
+     * available on passpoint network and if published by access point.
+     */
+    public CharSequence venueName;
+
+    /**
+     * Indicates passpoint operator name published by access point.
+     */
+    public CharSequence operatorFriendlyName;
 
     /**
      * {@hide}
@@ -267,7 +301,7 @@
      **/
     public byte[] bytes;
 
-    /** information element from beacon
+    /** information elements from beacon
      * @hide
      */
     public static class InformationElement {
@@ -303,8 +337,7 @@
         this.channelWidth = UNSPECIFIED;
         this.centerFreq0 = UNSPECIFIED;
         this.centerFreq1 = UNSPECIFIED;
-        this.is80211McRTTResponder = false;
-        this.passpointNetwork = false;
+        this.flags = 0;
     }
 
     /** {@hide} */
@@ -322,8 +355,7 @@
         this.channelWidth = UNSPECIFIED;
         this.centerFreq0 = UNSPECIFIED;
         this.centerFreq1 = UNSPECIFIED;
-        this.is80211McRTTResponder = false;
-        this.passpointNetwork = false;
+        this.flags = 0;
     }
 
     /** {@hide} */
@@ -342,8 +374,11 @@
         this.channelWidth = channelWidth;
         this.centerFreq0 = centerFreq0;
         this.centerFreq1 = centerFreq1;
-        this.is80211McRTTResponder = is80211McRTTResponder;
-        this.passpointNetwork = false;
+        if (is80211McRTTResponder) {
+            this.flags = FLAG_80211mc_RESPONDER;
+        } else {
+            this.flags = 0;
+        }
     }
 
     /** copy constructor {@hide} */
@@ -358,7 +393,6 @@
             channelWidth = source.channelWidth;
             centerFreq0 = source.centerFreq0;
             centerFreq1 = source.centerFreq1;
-            is80211McRTTResponder = source.is80211McRTTResponder;
             timestamp = source.timestamp;
             distanceCm = source.distanceCm;
             distanceSdCm = source.distanceSdCm;
@@ -369,9 +403,9 @@
             numUsage = source.numUsage;
             numIpConfigFailures = source.numIpConfigFailures;
             isAutoJoinCandidate = source.isAutoJoinCandidate;
-            passpointNetwork = source.passpointNetwork;
             venueName = source.venueName;
             operatorFriendlyName = source.operatorFriendlyName;
+            flags = source.flags;
         }
     }
 
@@ -405,15 +439,16 @@
         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
                 append("(cm)");
 
-        sb.append(", passpoint: ").append(passpointNetwork ? "yes" : "no");
+        sb.append(", passpoint: ");
+        sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no");
         if (autoJoinStatus != 0) {
             sb.append(", status: ").append(autoJoinStatus);
         }
         sb.append(", ChannelBandwidth: ").append(channelWidth);
         sb.append(", centerFreq0: ").append(centerFreq0);
         sb.append(", centerFreq1: ").append(centerFreq1);
-        sb.append(", 80211mcResponder: ").append(is80211McRTTResponder?
-                "is supported":"is not supported");
+        sb.append(", 80211mcResponder: ");
+        sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
         return sb.toString();
     }
 
@@ -440,7 +475,6 @@
         dest.writeInt(channelWidth);
         dest.writeInt(centerFreq0);
         dest.writeInt(centerFreq1);
-        dest.writeInt(is80211McRTTResponder ? 1 : 0);
         dest.writeLong(seen);
         dest.writeInt(autoJoinStatus);
         dest.writeInt(untrusted ? 1 : 0);
@@ -448,9 +482,9 @@
         dest.writeInt(numUsage);
         dest.writeInt(numIpConfigFailures);
         dest.writeInt(isAutoJoinCandidate);
-        dest.writeInt(passpointNetwork ? 1 : 0);
-        dest.writeString(venueName);
-        dest.writeString(operatorFriendlyName);
+        dest.writeString((venueName != null) ? venueName.toString() : "");
+        dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
+        dest.writeLong(this.flags);
 
         if (informationElements != null) {
             dest.writeInt(informationElements.length);
@@ -474,18 +508,19 @@
                 }
                 ScanResult sr = new ScanResult(
                     wifiSsid,
-                    in.readString(),
-                    in.readString(),
-                    in.readInt(),
-                    in.readInt(),
-                    in.readLong(),
-                    in.readInt(),
-                    in.readInt(),
-                    in.readInt(),
-                    in.readInt(),
-                    in.readInt(),
-                    in.readInt() == 1
+                    in.readString(),                    /* BSSID */
+                    in.readString(),                    /* capabilities */
+                    in.readInt(),                       /* level */
+                    in.readInt(),                       /* frequency */
+                    in.readLong(),                      /* timestamp */
+                    in.readInt(),                       /* distanceCm */
+                    in.readInt(),                       /* distanceSdCm */
+                    in.readInt(),                       /* channelWidth */
+                    in.readInt(),                       /* centerFreq0 */
+                    in.readInt(),                       /* centerFreq1 */
+                    false                               /* rtt responder, fixed with flags below */
                 );
+
                 sr.seen = in.readLong();
                 sr.autoJoinStatus = in.readInt();
                 sr.untrusted = in.readInt() != 0;
@@ -493,9 +528,9 @@
                 sr.numUsage = in.readInt();
                 sr.numIpConfigFailures = in.readInt();
                 sr.isAutoJoinCandidate = in.readInt();
-                sr.passpointNetwork = in.readInt() == 1;
                 sr.venueName = in.readString();
                 sr.operatorFriendlyName = in.readString();
+                sr.flags = in.readLong();
                 int n = in.readInt();
                 if (n != 0) {
                     sr.informationElements = new InformationElement[n];
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 5d55ec6..5d834f6 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -344,14 +344,15 @@
     public String FQDN;
 
     /**
-     * Service provider name, for Passpoint credential.
+     * Name of passpoint credential provider
      */
     public String providerFriendlyName;
 
     /**
-     * Roaming Consortium Id, for Passpoint credential.
+     * Roaming Consortium Id list for passpoint credential; identifies a set of networks where
+     * passpoint credential will be considered valid
      */
-    public HashSet<Long> roamingConsortiumIds;
+    public Long[] roamingConsortiumIds;
 
     /**
      * @hide
@@ -906,7 +907,7 @@
         SSID = null;
         BSSID = null;
         FQDN = null;
-        roamingConsortiumIds = new HashSet<Long>();
+        roamingConsortiumIds = new Long[0];
         priority = 0;
         hiddenSSID = false;
         disableReason = DISABLED_UNKNOWN_REASON;
@@ -1437,11 +1438,7 @@
             SSID = source.SSID;
             BSSID = source.BSSID;
             FQDN = source.FQDN;
-            roamingConsortiumIds = new HashSet<Long>();
-            for (Long roamingConsortiumId : source.roamingConsortiumIds) {
-                roamingConsortiumIds.add(roamingConsortiumId);
-            }
-
+            roamingConsortiumIds = source.roamingConsortiumIds.clone();
             providerFriendlyName = source.providerFriendlyName;
             preSharedKey = source.preSharedKey;
 
@@ -1546,7 +1543,7 @@
         dest.writeString(autoJoinBSSID);
         dest.writeString(FQDN);
         dest.writeString(providerFriendlyName);
-        dest.writeInt(roamingConsortiumIds.size());
+        dest.writeInt(roamingConsortiumIds.length);
         for (Long roamingConsortiumId : roamingConsortiumIds) {
             dest.writeLong(roamingConsortiumId);
         }
@@ -1622,8 +1619,9 @@
                 config.FQDN = in.readString();
                 config.providerFriendlyName = in.readString();
                 int numRoamingConsortiumIds = in.readInt();
+                config.roamingConsortiumIds = new Long[numRoamingConsortiumIds];
                 for (int i = 0; i < numRoamingConsortiumIds; i++) {
-                    config.roamingConsortiumIds.add(in.readLong());
+                    config.roamingConsortiumIds[i] = in.readLong();
                 }
                 config.preSharedKey = in.readString();
                 for (int i = 0; i < config.wepKeys.length; i++) {
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 3525ec2..e611ea4 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -604,12 +604,13 @@
      * Get the domain_suffix_match value. See setDomSuffixMatch.
      * @return The domain value.
      */
-    public String getDomainSubjectMatch() {
+    public String getDomainSuffixMatch() {
         return getFieldValue(DOM_SUFFIX_MATCH_KEY, "");
     }
 
     /**
-     * Set realm for passpoint credential
+     * Set realm for passpoint credential; realm identifies a set of networks where your
+     * passpoint credential can be used
      * @param realm the realm
      */
     public void setRealm(String realm) {
@@ -617,7 +618,7 @@
     }
 
     /**
-     * Get realm for passpoint credential
+     * Get realm for passpoint credential; see {@link #setRealm(String)} for more information
      * @return the realm
      */
     public String getRealm() {
@@ -625,15 +626,16 @@
     }
 
     /**
-     * Set plmn for passpoint credential
-     * @param plmn the plmn value derived from mcc & mnc
+     * Set plmn (Public Land Mobile Network) of the provider of passpoint credential
+     * @param plmn the plmn value derived from mcc (mobile country code) & mnc (mobile network code)
      */
     public void setPlmn(String plmn) {
         setFieldValue(PLMN_KEY, plmn, "");
     }
 
     /**
-     * Get plmn for passpoint credential
+     * Get plmn (Public Land Mobile Network) for passpoint credential; see {@link #setPlmn
+     * (String)} for more information
      * @return the plmn
      */
     public String getPlmn() {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 64fa0e5..d00c654 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -399,14 +399,16 @@
     public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
     /**
      * An access point scan has completed, and results are available from the supplicant.
-     * Call {@link #getScanResults()} to obtain the results.
+     * Call {@link #getScanResults()} to obtain the results. {@link #EXTRA_RESULTS_UPDATED}
+     * indicates if the scan was completed successfully.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
 
     /**
-     * The result of previous scan, reported with {@link #SCAN_RESULTS_AVAILABLE_ACTION}.
-     * @return true scan was successful, results updated
+     * Lookup key for a {@code boolean} representing the result of previous {@link #startScan}
+     * operation, reported with {@link #SCAN_RESULTS_AVAILABLE_ACTION}.
+     * @return true scan was successful, results are updated
      * @return false scan was not successful, results haven't been updated since previous scan
      */
     public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated";