Merge "Floating toolbar shown after rotation in extract mode" 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 0747d95..aa07a97 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -105,12 +105,9 @@
     field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
     field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
     field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
-    field public static final deprecated java.lang.String READ_PROFILE = "android.permission.READ_PROFILE";
     field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
-    field public static final deprecated java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM";
     field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
-    field public static final java.lang.String READ_USER_DICTIONARY = "android.permission.READ_USER_DICTIONARY";
     field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
     field public static final java.lang.String REBOOT = "android.permission.REBOOT";
     field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
@@ -152,12 +149,9 @@
     field public static final java.lang.String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS";
     field public static final java.lang.String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
     field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
-    field public static final deprecated java.lang.String WRITE_PROFILE = "android.permission.WRITE_PROFILE";
     field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
     field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
-    field public static final deprecated java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM";
     field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
-    field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission.WRITE_USER_DICTIONARY";
     field public static final java.lang.String WRITE_VOICEMAIL = "com.android.voicemail.permission.WRITE_VOICEMAIL";
   }
 
@@ -172,9 +166,7 @@
     field public static final java.lang.String PHONE = "android.permission-group.PHONE";
     field public static final java.lang.String SENSORS = "android.permission-group.SENSORS";
     field public static final java.lang.String SMS = "android.permission-group.SMS";
-    field public static final java.lang.String SOCIAL_INFO = "android.permission-group.SOCIAL_INFO";
     field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
-    field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
   }
 
   public final class R {
@@ -4016,79 +4008,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 +5819,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 +7195,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
@@ -12308,7 +12293,6 @@
     method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void invalidateSelf();
     method public boolean isAutoMirrored();
-    method public boolean isDither();
     method public boolean isFilterBitmap();
     method public boolean isStateful();
     method public final boolean isVisible();
@@ -12328,7 +12312,7 @@
     method public void setChangingConfigurations(int);
     method public abstract void setColorFilter(android.graphics.ColorFilter);
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public void setDither(boolean);
+    method public deprecated void setDither(boolean);
     method public void setFilterBitmap(boolean);
     method public void setHotspot(float, float);
     method public void setHotspotBounds(int, int, int, int);
@@ -12469,6 +12453,9 @@
     method public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
     method public void loadDrawableAsync(android.content.Context, android.os.Message);
     method public void loadDrawableAsync(android.content.Context, android.graphics.drawable.Icon.OnDrawableLoadedListener, android.os.Handler);
+    method public android.graphics.drawable.Icon setTint(int);
+    method public android.graphics.drawable.Icon setTintList(android.content.res.ColorStateList);
+    method public android.graphics.drawable.Icon setTintMode(android.graphics.PorterDuff.Mode);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.graphics.drawable.Icon> CREATOR;
   }
@@ -18207,7 +18194,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 +18344,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 +18359,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
@@ -25579,10 +25567,6 @@
     field public static final java.lang.String PHOTO_FILE_ID = "data14";
   }
 
-  public static final deprecated class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
-  }
-
   protected static abstract interface ContactsContract.ContactsColumns {
     field public static final java.lang.String CONTACT_LAST_UPDATED_TIMESTAMP = "contact_last_updated_timestamp";
     field public static final java.lang.String DISPLAY_NAME = "display_name";
@@ -25898,10 +25882,6 @@
     field public static final java.lang.String DATA_ID = "data_id";
   }
 
-  public static final deprecated class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
-  }
-
   protected static abstract interface ContactsContract.RawContactsColumns {
     field public static final java.lang.String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
     field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
@@ -25972,56 +25952,6 @@
     field public static final android.net.Uri PROFILE_CONTENT_URI;
   }
 
-  public static final deprecated class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
-    field public static final deprecated java.lang.String PHOTO = "photo";
-  }
-
-  protected static abstract deprecated interface ContactsContract.StreamItemPhotosColumns {
-    field public static final deprecated java.lang.String PHOTO_FILE_ID = "photo_file_id";
-    field public static final deprecated java.lang.String PHOTO_URI = "photo_uri";
-    field public static final deprecated java.lang.String SORT_INDEX = "sort_index";
-    field public static final deprecated java.lang.String STREAM_ITEM_ID = "stream_item_id";
-    field public static final deprecated java.lang.String SYNC1 = "stream_item_photo_sync1";
-    field public static final deprecated java.lang.String SYNC2 = "stream_item_photo_sync2";
-    field public static final deprecated java.lang.String SYNC3 = "stream_item_photo_sync3";
-    field public static final deprecated java.lang.String SYNC4 = "stream_item_photo_sync4";
-  }
-
-  public static final deprecated class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
-    field public static final deprecated android.net.Uri CONTENT_LIMIT_URI;
-    field public static final deprecated android.net.Uri CONTENT_PHOTO_URI;
-    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
-    field public static final deprecated android.net.Uri CONTENT_URI;
-    field public static final deprecated java.lang.String MAX_ITEMS = "max_items";
-  }
-
-  public static final deprecated class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
-    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo";
-    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
-    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
-  }
-
-  protected static abstract deprecated interface ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String ACCOUNT_NAME = "account_name";
-    field public static final deprecated java.lang.String ACCOUNT_TYPE = "account_type";
-    field public static final deprecated java.lang.String COMMENTS = "comments";
-    field public static final deprecated java.lang.String CONTACT_ID = "contact_id";
-    field public static final deprecated java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
-    field public static final deprecated java.lang.String DATA_SET = "data_set";
-    field public static final deprecated java.lang.String RAW_CONTACT_ID = "raw_contact_id";
-    field public static final deprecated java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
-    field public static final deprecated java.lang.String RES_ICON = "icon";
-    field public static final deprecated java.lang.String RES_LABEL = "label";
-    field public static final deprecated java.lang.String RES_PACKAGE = "res_package";
-    field public static final deprecated java.lang.String SYNC1 = "stream_item_sync1";
-    field public static final deprecated java.lang.String SYNC2 = "stream_item_sync2";
-    field public static final deprecated java.lang.String SYNC3 = "stream_item_sync3";
-    field public static final deprecated java.lang.String SYNC4 = "stream_item_sync4";
-    field public static final deprecated java.lang.String TEXT = "text";
-    field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
-  }
-
   protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
     field public static final java.lang.String ACCOUNT_NAME = "account_name";
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
@@ -28606,8 +28536,7 @@
     method public final void notifyCarrierNetworkChange(boolean);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier);
-    field public static final java.lang.String BIND_SERVICE_INTERFACE = "android.service.carrier.BindService";
-    field public static final java.lang.String CONFIG_SERVICE_INTERFACE = "android.service.carrier.ConfigService";
+    field public static final java.lang.String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";
   }
 
   public final class MessagePdu implements android.os.Parcelable {
@@ -36636,10 +36565,6 @@
     method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
-  public abstract deprecated class ViewAssistStructure extends android.view.ViewStructure {
-    ctor public ViewAssistStructure();
-  }
-
   public class ViewConfiguration {
     ctor public deprecated ViewConfiguration();
     method public static android.view.ViewConfiguration get(android.content.Context);
@@ -37021,7 +36946,7 @@
     ctor public ViewStructure();
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
-    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
+    method public abstract android.view.ViewStructure asyncNewChild(int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -37029,7 +36954,7 @@
     method public abstract int getTextSelectionEnd();
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
-    method public abstract android.view.ViewAssistStructure newChild(int);
+    method public abstract android.view.ViewStructure newChild(int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setCheckable(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index 2e6c685..7fc927b 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -117,6 +117,64 @@
     field public static final deprecated java.lang.String URL = "url";
   }
 
+  public static final deprecated class ContactsContract.Contacts.StreamItems {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
+  public static final deprecated class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
+  public static final deprecated class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String PHOTO = "photo";
+  }
+
+  protected static abstract deprecated interface ContactsContract.StreamItemPhotosColumns {
+    field public static final deprecated java.lang.String PHOTO_FILE_ID = "photo_file_id";
+    field public static final deprecated java.lang.String PHOTO_URI = "photo_uri";
+    field public static final deprecated java.lang.String SORT_INDEX = "sort_index";
+    field public static final deprecated java.lang.String STREAM_ITEM_ID = "stream_item_id";
+    field public static final deprecated java.lang.String SYNC1 = "stream_item_photo_sync1";
+    field public static final deprecated java.lang.String SYNC2 = "stream_item_photo_sync2";
+    field public static final deprecated java.lang.String SYNC3 = "stream_item_photo_sync3";
+    field public static final deprecated java.lang.String SYNC4 = "stream_item_photo_sync4";
+  }
+
+  public static final deprecated class ContactsContract.StreamItems implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
+    field public static final deprecated android.net.Uri CONTENT_LIMIT_URI;
+    field public static final deprecated android.net.Uri CONTENT_PHOTO_URI;
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String MAX_ITEMS = "max_items";
+  }
+
+  public static final deprecated class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
+  }
+
+  protected static abstract deprecated interface ContactsContract.StreamItemsColumns {
+    field public static final deprecated java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final deprecated java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final deprecated java.lang.String COMMENTS = "comments";
+    field public static final deprecated java.lang.String CONTACT_ID = "contact_id";
+    field public static final deprecated java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
+    field public static final deprecated java.lang.String DATA_SET = "data_set";
+    field public static final deprecated java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+    field public static final deprecated java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
+    field public static final deprecated java.lang.String RES_ICON = "icon";
+    field public static final deprecated java.lang.String RES_LABEL = "label";
+    field public static final deprecated java.lang.String RES_PACKAGE = "res_package";
+    field public static final deprecated java.lang.String SYNC1 = "stream_item_sync1";
+    field public static final deprecated java.lang.String SYNC2 = "stream_item_sync2";
+    field public static final deprecated java.lang.String SYNC3 = "stream_item_sync3";
+    field public static final deprecated java.lang.String SYNC4 = "stream_item_sync4";
+    field public static final deprecated java.lang.String TEXT = "text";
+    field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
+  }
+
   public static final class Settings.System extends android.provider.Settings.NameValueTable {
     field public static final java.lang.String APPEND_FOR_LAST_AUDIBLE = "_last_audible";
     field public static final java.lang.String VOLUME_ALARM = "volume_alarm";
diff --git a/api/system-current.txt b/api/system-current.txt
index bb0c7f3..a245a3e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -156,13 +156,10 @@
     field public static final java.lang.String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
     field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
     field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
-    field public static final deprecated java.lang.String READ_PROFILE = "android.permission.READ_PROFILE";
     field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
     field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
-    field public static final deprecated java.lang.String READ_SOCIAL_STREAM = "android.permission.READ_SOCIAL_STREAM";
     field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
-    field public static final java.lang.String READ_USER_DICTIONARY = "android.permission.READ_USER_DICTIONARY";
     field public static final java.lang.String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
     field public static final java.lang.String READ_WIFI_CREDENTIAL = "android.permission.READ_WIFI_CREDENTIAL";
     field public static final java.lang.String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
@@ -227,12 +224,9 @@
     field public static final java.lang.String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
     field public static final java.lang.String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
     field public static final java.lang.String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
-    field public static final deprecated java.lang.String WRITE_PROFILE = "android.permission.WRITE_PROFILE";
     field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
     field public static final java.lang.String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
-    field public static final deprecated java.lang.String WRITE_SOCIAL_STREAM = "android.permission.WRITE_SOCIAL_STREAM";
     field public static final java.lang.String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
-    field public static final java.lang.String WRITE_USER_DICTIONARY = "android.permission.WRITE_USER_DICTIONARY";
     field public static final java.lang.String WRITE_VOICEMAIL = "com.android.voicemail.permission.WRITE_VOICEMAIL";
   }
 
@@ -247,9 +241,7 @@
     field public static final java.lang.String PHONE = "android.permission-group.PHONE";
     field public static final java.lang.String SENSORS = "android.permission-group.SENSORS";
     field public static final java.lang.String SMS = "android.permission-group.SMS";
-    field public static final java.lang.String SOCIAL_INFO = "android.permission-group.SOCIAL_INFO";
     field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
-    field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
   }
 
   public final class R {
@@ -4112,79 +4104,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 +5937,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 +7420,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
@@ -12634,7 +12619,6 @@
     method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void invalidateSelf();
     method public boolean isAutoMirrored();
-    method public boolean isDither();
     method public boolean isFilterBitmap();
     method public boolean isStateful();
     method public final boolean isVisible();
@@ -12654,7 +12638,7 @@
     method public void setChangingConfigurations(int);
     method public abstract void setColorFilter(android.graphics.ColorFilter);
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public void setDither(boolean);
+    method public deprecated void setDither(boolean);
     method public void setFilterBitmap(boolean);
     method public void setHotspot(float, float);
     method public void setHotspotBounds(int, int, int, int);
@@ -12795,6 +12779,9 @@
     method public android.graphics.drawable.Drawable loadDrawable(android.content.Context);
     method public void loadDrawableAsync(android.content.Context, android.os.Message);
     method public void loadDrawableAsync(android.content.Context, android.graphics.drawable.Icon.OnDrawableLoadedListener, android.os.Handler);
+    method public android.graphics.drawable.Icon setTint(int);
+    method public android.graphics.drawable.Icon setTintList(android.content.res.ColorStateList);
+    method public android.graphics.drawable.Icon setTintMode(android.graphics.PorterDuff.Mode);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.graphics.drawable.Icon> CREATOR;
   }
@@ -19708,7 +19695,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 +19845,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 +19860,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
@@ -27524,10 +27512,6 @@
     field public static final java.lang.String PHOTO_FILE_ID = "data14";
   }
 
-  public static final deprecated class ContactsContract.Contacts.StreamItems implements android.provider.ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
-  }
-
   protected static abstract interface ContactsContract.ContactsColumns {
     field public static final java.lang.String CONTACT_LAST_UPDATED_TIMESTAMP = "contact_last_updated_timestamp";
     field public static final java.lang.String DISPLAY_NAME = "display_name";
@@ -27843,10 +27827,6 @@
     field public static final java.lang.String DATA_ID = "data_id";
   }
 
-  public static final deprecated class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
-  }
-
   protected static abstract interface ContactsContract.RawContactsColumns {
     field public static final java.lang.String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
     field public static final java.lang.String AGGREGATION_MODE = "aggregation_mode";
@@ -27917,56 +27897,6 @@
     field public static final android.net.Uri PROFILE_CONTENT_URI;
   }
 
-  public static final deprecated class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
-    field public static final deprecated java.lang.String PHOTO = "photo";
-  }
-
-  protected static abstract deprecated interface ContactsContract.StreamItemPhotosColumns {
-    field public static final deprecated java.lang.String PHOTO_FILE_ID = "photo_file_id";
-    field public static final deprecated java.lang.String PHOTO_URI = "photo_uri";
-    field public static final deprecated java.lang.String SORT_INDEX = "sort_index";
-    field public static final deprecated java.lang.String STREAM_ITEM_ID = "stream_item_id";
-    field public static final deprecated java.lang.String SYNC1 = "stream_item_photo_sync1";
-    field public static final deprecated java.lang.String SYNC2 = "stream_item_photo_sync2";
-    field public static final deprecated java.lang.String SYNC3 = "stream_item_photo_sync3";
-    field public static final deprecated java.lang.String SYNC4 = "stream_item_photo_sync4";
-  }
-
-  public static final deprecated class ContactsContract.StreamItems implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
-    field public static final deprecated android.net.Uri CONTENT_LIMIT_URI;
-    field public static final deprecated android.net.Uri CONTENT_PHOTO_URI;
-    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
-    field public static final deprecated android.net.Uri CONTENT_URI;
-    field public static final deprecated java.lang.String MAX_ITEMS = "max_items";
-  }
-
-  public static final deprecated class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns android.provider.ContactsContract.StreamItemPhotosColumns {
-    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo";
-    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
-    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
-  }
-
-  protected static abstract deprecated interface ContactsContract.StreamItemsColumns {
-    field public static final deprecated java.lang.String ACCOUNT_NAME = "account_name";
-    field public static final deprecated java.lang.String ACCOUNT_TYPE = "account_type";
-    field public static final deprecated java.lang.String COMMENTS = "comments";
-    field public static final deprecated java.lang.String CONTACT_ID = "contact_id";
-    field public static final deprecated java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
-    field public static final deprecated java.lang.String DATA_SET = "data_set";
-    field public static final deprecated java.lang.String RAW_CONTACT_ID = "raw_contact_id";
-    field public static final deprecated java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
-    field public static final deprecated java.lang.String RES_ICON = "icon";
-    field public static final deprecated java.lang.String RES_LABEL = "label";
-    field public static final deprecated java.lang.String RES_PACKAGE = "res_package";
-    field public static final deprecated java.lang.String SYNC1 = "stream_item_sync1";
-    field public static final deprecated java.lang.String SYNC2 = "stream_item_sync2";
-    field public static final deprecated java.lang.String SYNC3 = "stream_item_sync3";
-    field public static final deprecated java.lang.String SYNC4 = "stream_item_sync4";
-    field public static final deprecated java.lang.String TEXT = "text";
-    field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
-  }
-
   protected static abstract interface ContactsContract.SyncColumns implements android.provider.ContactsContract.BaseSyncColumns {
     field public static final java.lang.String ACCOUNT_NAME = "account_name";
     field public static final java.lang.String ACCOUNT_TYPE = "account_type";
@@ -30654,8 +30584,7 @@
     method public final void notifyCarrierNetworkChange(boolean);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier);
-    field public static final java.lang.String BIND_SERVICE_INTERFACE = "android.service.carrier.BindService";
-    field public static final java.lang.String CONFIG_SERVICE_INTERFACE = "android.service.carrier.ConfigService";
+    field public static final java.lang.String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";
   }
 
   public final class MessagePdu implements android.os.Parcelable {
@@ -38917,10 +38846,6 @@
     method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
   }
 
-  public abstract deprecated class ViewAssistStructure extends android.view.ViewStructure {
-    ctor public ViewAssistStructure();
-  }
-
   public class ViewConfiguration {
     ctor public deprecated ViewConfiguration();
     method public static android.view.ViewConfiguration get(android.content.Context);
@@ -39302,7 +39227,7 @@
     ctor public ViewStructure();
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
-    method public abstract android.view.ViewAssistStructure asyncNewChild(int);
+    method public abstract android.view.ViewStructure asyncNewChild(int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -39310,7 +39235,7 @@
     method public abstract int getTextSelectionEnd();
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
-    method public abstract android.view.ViewAssistStructure newChild(int);
+    method public abstract android.view.ViewStructure newChild(int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setCheckable(boolean);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 2e6c685..7fc927b 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -117,6 +117,64 @@
     field public static final deprecated java.lang.String URL = "url";
   }
 
+  public static final deprecated class ContactsContract.Contacts.StreamItems {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
+  public static final deprecated class ContactsContract.RawContacts.StreamItems implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "stream_items";
+  }
+
+  public static final deprecated class ContactsContract.StreamItemPhotos implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String PHOTO = "photo";
+  }
+
+  protected static abstract deprecated interface ContactsContract.StreamItemPhotosColumns {
+    field public static final deprecated java.lang.String PHOTO_FILE_ID = "photo_file_id";
+    field public static final deprecated java.lang.String PHOTO_URI = "photo_uri";
+    field public static final deprecated java.lang.String SORT_INDEX = "sort_index";
+    field public static final deprecated java.lang.String STREAM_ITEM_ID = "stream_item_id";
+    field public static final deprecated java.lang.String SYNC1 = "stream_item_photo_sync1";
+    field public static final deprecated java.lang.String SYNC2 = "stream_item_photo_sync2";
+    field public static final deprecated java.lang.String SYNC3 = "stream_item_photo_sync3";
+    field public static final deprecated java.lang.String SYNC4 = "stream_item_photo_sync4";
+  }
+
+  public static final deprecated class ContactsContract.StreamItems implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item";
+    field public static final deprecated android.net.Uri CONTENT_LIMIT_URI;
+    field public static final deprecated android.net.Uri CONTENT_PHOTO_URI;
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item";
+    field public static final deprecated android.net.Uri CONTENT_URI;
+    field public static final deprecated java.lang.String MAX_ITEMS = "max_items";
+  }
+
+  public static final deprecated class ContactsContract.StreamItems.StreamItemPhotos implements android.provider.BaseColumns {
+    field public static final deprecated java.lang.String CONTENT_DIRECTORY = "photo";
+    field public static final deprecated java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/stream_item_photo";
+    field public static final deprecated java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/stream_item_photo";
+  }
+
+  protected static abstract deprecated interface ContactsContract.StreamItemsColumns {
+    field public static final deprecated java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final deprecated java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final deprecated java.lang.String COMMENTS = "comments";
+    field public static final deprecated java.lang.String CONTACT_ID = "contact_id";
+    field public static final deprecated java.lang.String CONTACT_LOOKUP_KEY = "contact_lookup";
+    field public static final deprecated java.lang.String DATA_SET = "data_set";
+    field public static final deprecated java.lang.String RAW_CONTACT_ID = "raw_contact_id";
+    field public static final deprecated java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
+    field public static final deprecated java.lang.String RES_ICON = "icon";
+    field public static final deprecated java.lang.String RES_LABEL = "label";
+    field public static final deprecated java.lang.String RES_PACKAGE = "res_package";
+    field public static final deprecated java.lang.String SYNC1 = "stream_item_sync1";
+    field public static final deprecated java.lang.String SYNC2 = "stream_item_sync2";
+    field public static final deprecated java.lang.String SYNC3 = "stream_item_sync3";
+    field public static final deprecated java.lang.String SYNC4 = "stream_item_sync4";
+    field public static final deprecated java.lang.String TEXT = "text";
+    field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
+  }
+
   public static final class Settings.System extends android.provider.Settings.NameValueTable {
     field public static final java.lang.String APPEND_FOR_LAST_AUDIBLE = "_last_audible";
     field public static final java.lang.String VOLUME_ALARM = "volume_alarm";
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/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 993b53d..3001c2c 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -209,7 +209,8 @@
     /**
      * Bundle key used to supply the last time the credentials of the account
      * were authenticated successfully. Time is specified in milliseconds since
-     * epoch.
+     * epoch. Associated time is updated on successful authentication of account
+     * on adding account, confirming credentials, or updating credentials.
      */
     public static final String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime";
 
@@ -651,18 +652,25 @@
     }
 
     /**
-     * Adds an account directly to the AccountManager.  Normally used by sign-up
+     * Adds an account directly to the AccountManager. Normally used by sign-up
      * wizards associated with authenticators, not directly by applications.
-     *
+     * <p>Calling this method does not update the last authenticated timestamp,
+     * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
+     * {@link #notifyAccountAuthenticated(Account)} after getting success.
+     * However, if this method is called when it is triggered by addAccount() or
+     * addAccountAsUser() or similar functions, then there is no need to update
+     * timestamp manually as it is updated automatically by framework on
+     * successful completion of the mentioned functions.
      * <p>It is safe to call this method from the main thread.
      * <p>This method requires the caller to have a signature match with the
      * authenticator that owns the specified account.
      *
      * @param account The {@link Account} to add
      * @param password The password to associate with the account, null for none
-     * @param userdata String values to use for the account's userdata, null for none
+     * @param userdata String values to use for the account's userdata, null for
+     *            none
      * @return True if the account was successfully added, false if the account
-     *     already exists, the account is null, or another error occurs.
+     *         already exists, the account is null, or another error occurs.
      */
     public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
         if (account == null) throw new IllegalArgumentException("account is null");
@@ -976,17 +984,19 @@
     }
 
     /**
-     * Sets or forgets a saved password.  This modifies the local copy of the
-     * password used to automatically authenticate the user; it does
-     * not change the user's account password on the server.  Intended for use
-     * by the authenticator, not directly by applications.
-     *
+     * Sets or forgets a saved password. This modifies the local copy of the
+     * password used to automatically authenticate the user; it does not change
+     * the user's account password on the server. Intended for use by the
+     * authenticator, not directly by applications.
+     * <p>Calling this method does not update the last authenticated timestamp,
+     * referred by {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
+     * {@link #notifyAccountAuthenticated(Account)} after getting success.
      * <p>It is safe to call this method from the main thread.
-     *
      * <p>This method requires the caller to have a signature match with the
      * authenticator that manages the specified account.
      *
-     * @param account The account whose password is to be set. Cannot be {@code null}.
+     * @param account The account whose password is to be set. Cannot be
+     *            {@code null}.
      * @param password The password to set, null to clear the password
      */
     public void setPassword(final Account account, final String password) {
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/Notification.java b/core/java/android/app/Notification.java
index 5a0d246..aa68345 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3586,12 +3586,19 @@
          * object.
          */
         public Notification build() {
+            if (mSmallIcon != null) {
+                mSmallIcon.convertToAshmem();
+            }
+            if (mLargeIcon != null) {
+                mLargeIcon.convertToAshmem();
+            }
             mOriginatingUserId = mContext.getUserId();
             mHasThreeLines = hasThreeLines();
 
             Notification n = buildUnstyled();
 
             if (mStyle != null) {
+                mStyle.purgeResources();
                 n = mStyle.buildStyled(n);
             }
 
@@ -3790,6 +3797,11 @@
             return wip;
         }
 
+        /**
+         * @hide
+         */
+        public void purgeResources() {}
+
         // The following methods are split out so we can re-create notification partially.
         /**
          * @hide
@@ -3901,8 +3913,21 @@
             return this;
         }
 
-        private RemoteViews makeBigContentView() {
+        /**
+         * @hide
+         */
+        @Override
+        public void purgeResources() {
+            super.purgeResources();
+            if (mPicture != null && mPicture.isMutable()) {
+                mPicture = mPicture.createAshmemBitmap();
+            }
+            if (mBigLargeIcon != null) {
+                mBigLargeIcon.convertToAshmem();
+            }
+        }
 
+        private RemoteViews makeBigContentView() {
             // Replace mLargeIcon with mBigLargeIcon if mBigLargeIconSet
             // This covers the following cases:
             //   1. mBigLargeIconSet -> mBigLargeIcon (null or non-null) applies, overrides
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 b859dca..4d1cff5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4350,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..284dfd6 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.ViewStructure;
+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 ViewStructure {
+        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 ViewStructure newChild(int index) {
+            ViewNode node = new ViewNode();
+            mNode.mChildren[index] = node;
+            return new ViewNodeBuilder(mAssist, node, false);
+        }
+
+        @Override
+        public ViewStructure 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 ViewStructure.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/view/ViewAssistStructure.java b/core/java/android/content/pm/IPackagesProvider.aidl
similarity index 78%
rename from core/java/android/view/ViewAssistStructure.java
rename to core/java/android/content/pm/IPackagesProvider.aidl
index a66d93c..7d76c88 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/android/content/pm/IPackagesProvider.aidl
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.content.pm;
 
-/**
- * @deprecated Temporary until old apps can move off this.
- */
-@Deprecated
-public abstract class ViewAssistStructure extends ViewStructure {
+/** {@hide} */
+interface IPackagesProvider {
+    String[] getPackages(int userId);
 }
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 4e7da48..04dbff2 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -109,6 +109,14 @@
     public static final int FLAG_COSTS_MONEY = 1<<0;
 
     /**
+     * Flag for {@link #protectionLevel}, corresponding
+     * to the <code>hide</code> value of
+     * {@link android.R.attr#permissionFlags}.
+     * @hide
+     */
+    public static final int PROTECTION_FLAG_HIDE = 1<<1;
+
+    /**
      * Additional flags about this permission as given by
      * {@link android.R.attr#permissionFlags}.
      */
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 261ce72..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 =
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index e405ba6..75289f7 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -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/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 70afe5b..57a080b 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -284,6 +284,8 @@
      * {@code offset + 2 * width * height)} bytes.  The width and height of
      * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
      * and will typically be equal to the width and height of
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE}.  Prior to
+     * API level 23, this was always the same as
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
      * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
      * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}.  If insufficient
@@ -332,6 +334,8 @@
      * {@code offset + 2 * width * height)} bytes.  The width and height of
      * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
      * and will typically be equal to the width and height of
+     * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE}.  Prior to
+     * API level 23, this was always the same as
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
      * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
      * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}.  If insufficient
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 0935564..639ad60 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -20,6 +20,7 @@
 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;
@@ -484,31 +485,35 @@
 
     /**
      * 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();
@@ -517,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);
@@ -558,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() {
@@ -594,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
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/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index aebe7f1..8ce1cbf 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1743,6 +1743,9 @@
          *
          * @deprecated - Do not use. This will not be supported in the future. In the future,
          * cursors returned from related queries will be empty.
+         *
+         * @hide
+         * @removed
          */
         @Deprecated
         public static final class StreamItems implements StreamItemsColumns {
@@ -2831,6 +2834,9 @@
          *
          * @deprecated - Do not use. This will not be supported in the future. In the future,
          * cursors returned from related queries will be empty.
+         *
+         * @hide
+         * @removed
          */
         @Deprecated
         public static final class StreamItems implements BaseColumns, StreamItemsColumns {
@@ -3267,6 +3273,9 @@
      *
      * @deprecated - Do not use. This will not be supported in the future. In the future,
      * cursors returned from related queries will be empty.
+     *
+     * @hide
+     * @removed
      */
     @Deprecated
     public static final class StreamItems implements BaseColumns, StreamItemsColumns {
@@ -3365,6 +3374,9 @@
          *
          * @deprecated - Do not use. This will not be supported in the future. In the future,
          * cursors returned from related queries will be empty.
+         *
+         * @hide
+         * @removed
          */
         @Deprecated
         public static final class StreamItemPhotos
@@ -3415,6 +3427,9 @@
      * @see ContactsContract.StreamItems
      * @deprecated - Do not use. This will not be supported in the future. In the future,
      * cursors returned from related queries will be empty.
+     *
+     * @hide
+     * @removed
      */
     @Deprecated
     protected interface StreamItemsColumns {
@@ -3805,6 +3820,9 @@
      *
      * @deprecated - Do not use. This will not be supported in the future. In the future,
      * cursors returned from related queries will be empty.
+     *
+     * @hide
+     * @removed
      */
     @Deprecated
     public static final class StreamItemPhotos implements BaseColumns, StreamItemPhotosColumns {
@@ -3843,6 +3861,9 @@
      * @see ContactsContract.StreamItemPhotos
      * @deprecated - Do not use. This will not be supported in the future. In the future,
      * cursors returned from related queries will be empty.
+     *
+     * @hide
+     * @removed
      */
     @Deprecated
     protected interface StreamItemPhotosColumns {
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/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 225e70d..455e1b2 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -29,8 +29,8 @@
  * <p>
  * To extend this class, you must declare the service in your manifest file to require the
  * {@link android.Manifest.permission#BIND_CARRIER_SERVICES} permission and include an intent
- * filter with the {@link #CONFIG_SERVICE_INTERFACE} action if the service exposes carrier config
- * and the {@link #BIND_SERVICE_INTERFACE} action if the service should have a long-lived binding.
+ * filter with the {@link #CARRIER_SERVICE_INTERFACE}. If the service should have a long-lived
+ * binding, set android.service.carrier.LONG_LIVED_BINDING to true in the service's metadata.
  * For example:
  * </p>
  *
@@ -39,16 +39,16 @@
  *       android:label="@string/service_name"
  *       android:permission="android.permission.BIND_CARRIER_SERVICES">
  *  <intent-filter>
- *      <action android:name="android.service.carrier.ConfigService" />
- *      <action android:name="android.service.carrier.BindService" />
+ *      <action android:name="android.service.carrier.CarrierService" />
  *  </intent-filter>
+ *  <meta-data android:name="android.service.carrier.LONG_LIVED_BINDING"
+ *             android:value="true" />
  * </service>
  * }</pre>
  */
 public abstract class CarrierService extends Service {
 
-    public static final String CONFIG_SERVICE_INTERFACE = "android.service.carrier.ConfigService";
-    public static final String BIND_SERVICE_INTERFACE = "android.service.carrier.BindService";
+    public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";
 
     private static ITelephonyRegistry sRegistry;
 
@@ -127,13 +127,7 @@
     @Override
     @CallSuper
     public IBinder onBind(Intent intent) {
-        switch (intent.getAction()) {
-            case CONFIG_SERVICE_INTERFACE:
-            case BIND_SERVICE_INTERFACE:
-                return mStubWrapper;
-            default:
-                return null;
-        }
+        return mStubWrapper;
     }
 
     /**
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/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/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..502a6bc 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) {
@@ -21037,6 +21041,9 @@
             if (sUseBrokenMakeMeasureSpec) {
                 return size + mode;
             } else {
+                if (size < 0) {
+                    throw new IllegalArgumentException("Measure spec size must be >= 0");
+                }
                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
             }
         }
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index d06cd83..9ab0ace 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);
 
@@ -221,7 +221,7 @@
      * children at <var>index</var>.
      * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
-    public abstract ViewAssistStructure newChild(int index);
+    public abstract ViewStructure newChild(int index);
 
     /**
      * Like {@link #newChild}, but allows the caller to asynchronously populate the returned
@@ -231,7 +231,7 @@
      * population is done.
      * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
-    public abstract ViewAssistStructure asyncNewChild(int index);
+    public abstract ViewStructure asyncNewChild(int index);
 
     /**
      * Call when done populating a {@link ViewStructure} returned by
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/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 15ed5bd..0abd200 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -23,6 +23,8 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.*;
 
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
 import android.app.ActivityManagerNative;
 import android.app.SearchManager;
 import android.os.UserHandle;
@@ -2216,6 +2218,7 @@
         private OnPreDrawListener mFloatingToolbarPreDrawListener;
         private View mFloatingActionModeOriginatingView;
         private FloatingToolbar mFloatingToolbar;
+        private ObjectAnimator mFadeAnim;
 
         // View added at runtime to draw under the status bar area
         private View mStatusGuard;
@@ -3345,6 +3348,7 @@
         }
 
         private ActionMode createStandaloneActionMode(ActionMode.Callback callback) {
+            endOnGoingFadeAnimation();
             cleanupPrimaryActionMode();
             if (mPrimaryActionModeView == null) {
                 if (isFloating()) {
@@ -3384,6 +3388,32 @@
                             mPrimaryActionModePopup.showAtLocation(
                                     mPrimaryActionModeView.getApplicationWindowToken(),
                                     Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
+                            endOnGoingFadeAnimation();
+                            mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
+                                    0f, 1f);
+                            mFadeAnim.addListener(new Animator.AnimatorListener() {
+                                @Override
+                                public void onAnimationStart(Animator animation) {
+                                    mPrimaryActionModeView.setVisibility(VISIBLE);
+                                }
+
+                                @Override
+                                public void onAnimationEnd(Animator animation) {
+                                    mPrimaryActionModeView.setAlpha(1f);
+                                    mFadeAnim = null;
+                                }
+
+                                @Override
+                                public void onAnimationCancel(Animator animation) {
+
+                                }
+
+                                @Override
+                                public void onAnimationRepeat(Animator animation) {
+
+                                }
+                            });
+                            mFadeAnim.start();
                         }
                     };
                 } else {
@@ -3404,13 +3434,44 @@
             return null;
         }
 
+        private void endOnGoingFadeAnimation() {
+            if (mFadeAnim != null) {
+                mFadeAnim.end();
+            }
+        }
+
         private void setHandledPrimaryActionMode(ActionMode mode) {
+            endOnGoingFadeAnimation();
             mPrimaryActionMode = mode;
             mPrimaryActionMode.invalidate();
             mPrimaryActionModeView.initForMode(mPrimaryActionMode);
-            mPrimaryActionModeView.setVisibility(View.VISIBLE);
             if (mPrimaryActionModePopup != null) {
                 post(mShowPrimaryActionModePopup);
+            } else {
+                mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA, 0f, 1f);
+                mFadeAnim.addListener(new Animator.AnimatorListener() {
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        mPrimaryActionModeView.setVisibility(View.VISIBLE);
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mPrimaryActionModeView.setAlpha(1f);
+                        mFadeAnim = null;
+                    }
+
+                    @Override
+                    public void onAnimationCancel(Animator animation) {
+
+                    }
+
+                    @Override
+                    public void onAnimationRepeat(Animator animation) {
+
+                    }
+                });
+                mFadeAnim.start();
             }
             mPrimaryActionModeView.sendAccessibilityEvent(
                     AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
@@ -3473,13 +3534,40 @@
                 if (mode == mPrimaryActionMode) {
                     if (mPrimaryActionModePopup != null) {
                         removeCallbacks(mShowPrimaryActionModePopup);
-                        mPrimaryActionModePopup.dismiss();
-                    } else if (mPrimaryActionModeView != null) {
-                        mPrimaryActionModeView.setVisibility(GONE);
                     }
                     if (mPrimaryActionModeView != null) {
-                        mPrimaryActionModeView.removeAllViews();
+                        endOnGoingFadeAnimation();
+                        mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
+                                1f, 0f);
+                        mFadeAnim.addListener(new Animator.AnimatorListener() {
+                                    @Override
+                                    public void onAnimationStart(Animator animation) {
+
+                                    }
+
+                                    @Override
+                                    public void onAnimationEnd(Animator animation) {
+                                        mPrimaryActionModeView.setVisibility(GONE);
+                                        if (mPrimaryActionModePopup != null) {
+                                            mPrimaryActionModePopup.dismiss();
+                                        }
+                                        mPrimaryActionModeView.removeAllViews();
+                                        mFadeAnim = null;
+                                    }
+
+                                    @Override
+                                    public void onAnimationCancel(Animator animation) {
+
+                                    }
+
+                                    @Override
+                                    public void onAnimationRepeat(Animator animation) {
+
+                                    }
+                                });
+                        mFadeAnim.start();
                     }
+
                     mPrimaryActionMode = null;
                 } else if (mode == mFloatingActionMode) {
                     cleanupFloatingActionModeViews();
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/android/view/ViewAssistStructure.java b/core/java/com/android/internal/statusbar/NotificationVisibility.aidl
similarity index 64%
copy from core/java/android/view/ViewAssistStructure.java
copy to core/java/com/android/internal/statusbar/NotificationVisibility.aidl
index a66d93c..c067551 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/com/android/internal/statusbar/NotificationVisibility.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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
+ *     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,
@@ -14,11 +14,7 @@
  * limitations under the License.
  */
 
-package android.view;
+package com.android.internal.statusbar;
 
-/**
- * @deprecated Temporary until old apps can move off this.
- */
-@Deprecated
-public abstract class ViewAssistStructure extends ViewStructure {
-}
+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_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 9b5fb3a..2116da0 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -175,24 +175,24 @@
 static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
                          jfloat r, jfloat b, jint opHandle) {
     SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
-    bool emptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
-    return emptyClip ? JNI_FALSE : JNI_TRUE;
+    bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
+    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
 }
 
 static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
                          jint opHandle) {
     SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
     SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
-    bool emptyClip = get_canvas(canvasHandle)->clipPath(path, op);
-    return emptyClip ? JNI_FALSE : JNI_TRUE;
+    bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op);
+    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
 }
 
 static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
                            jint opHandle) {
     SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
     SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
-    bool emptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
-    return emptyClip ? JNI_FALSE : JNI_TRUE;
+    bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
+    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
 }
 
 static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
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_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 7d8d151..995d39f 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "DngCreator_JNI"
 #include <inttypes.h>
 #include <string.h>
+#include <algorithm>
+#include <memory>
 
 #include <utils/Log.h>
 #include <utils/Errors.h>
@@ -25,7 +27,6 @@
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 #include <cutils/properties.h>
-
 #include <system/camera_metadata.h>
 #include <camera/CameraMetadata.h>
 #include <img_utils/DngUtils.h>
@@ -37,15 +38,6 @@
 #include <img_utils/StripSource.h>
 
 #include "core_jni_helpers.h"
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/StrongPointer.h>
-#include <utils/RefBase.h>
-#include <utils/Vector.h>
-#include <cutils/properties.h>
-
-#include <string.h>
-#include <inttypes.h>
 
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_hardware_camera2_CameraMetadata.h"
@@ -63,6 +55,14 @@
         return; \
     }
 
+#define BAIL_IF_INVALID_R(expr, jnienv, tagId, writer) \
+    if ((expr) != OK) { \
+        jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+                "Invalid metadata for tag %s (%x)", (writer)->getTagName(tagId), (tagId)); \
+        return -1; \
+    }
+
+
 #define BAIL_IF_EMPTY(entry, jnienv, tagId, writer) \
     if (entry.count == 0) { \
         jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
@@ -111,11 +111,14 @@
 class NativeContext : public LightRefBase<NativeContext> {
 
 public:
-    NativeContext();
+    NativeContext(const CameraMetadata& characteristics, const CameraMetadata& result);
     virtual ~NativeContext();
 
     TiffWriter* getWriter();
 
+    std::shared_ptr<const CameraMetadata> getCharacteristics() const;
+    std::shared_ptr<const CameraMetadata> getResult() const;
+
     uint32_t getThumbnailWidth();
     uint32_t getThumbnailHeight();
     const uint8_t* getThumbnail();
@@ -125,11 +128,16 @@
 private:
     Vector<uint8_t> mCurrentThumbnail;
     TiffWriter mWriter;
+    std::shared_ptr<CameraMetadata> mCharacteristics;
+    std::shared_ptr<CameraMetadata> mResult;
     uint32_t mThumbnailWidth;
     uint32_t mThumbnailHeight;
 };
 
-NativeContext::NativeContext() : mThumbnailWidth(0), mThumbnailHeight(0) {}
+NativeContext::NativeContext(const CameraMetadata& characteristics, const CameraMetadata& result) :
+        mCharacteristics(std::make_shared<CameraMetadata>(characteristics)),
+        mResult(std::make_shared<CameraMetadata>(result)), mThumbnailWidth(0),
+        mThumbnailHeight(0) {}
 
 NativeContext::~NativeContext() {}
 
@@ -137,6 +145,14 @@
     return &mWriter;
 }
 
+std::shared_ptr<const CameraMetadata> NativeContext::getCharacteristics() const {
+    return mCharacteristics;
+}
+
+std::shared_ptr<const CameraMetadata> NativeContext::getResult() const {
+    return mResult;
+}
+
 uint32_t NativeContext::getThumbnailWidth() {
     return mThumbnailWidth;
 }
@@ -626,25 +642,92 @@
 // End of DirectStripSource
 // ----------------------------------------------------------------------------
 
-static bool validateDngHeader(JNIEnv* env, TiffWriter* writer, jint width, jint height) {
-    bool hasThumbnail = writer->hasIfd(TIFF_IFD_SUB1);
+/**
+ * Given a buffer crop rectangle relative to the pixel array size, and the active array crop
+ * rectangle for the camera characteristics, set the default crop rectangle in the TiffWriter
+ * relative to the buffer crop rectangle origin.
+ */
+static status_t calculateAndSetCrop(JNIEnv* env, const CameraMetadata& characteristics,
+        uint32_t bufXMin, uint32_t bufYMin, uint32_t bufWidth, uint32_t bufHeight,
+        TiffWriter* writer) {
 
+    camera_metadata_ro_entry entry =
+            characteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+    uint32_t xmin = static_cast<uint32_t>(entry.data.i32[0]);
+    uint32_t ymin = static_cast<uint32_t>(entry.data.i32[1]);
+    uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
+    uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
+
+    uint32_t aLeft = xmin;
+    uint32_t aTop = ymin;
+    uint32_t aRight = xmin + width;
+    uint32_t aBottom = ymin + height;
+
+    const uint32_t margin = 8; // Default margin recommended by Adobe for interpolation.
+
+    uint32_t bLeft = bufXMin + margin;
+    uint32_t bTop = bufYMin + margin;
+    uint32_t bRight = bufXMin + bufWidth - margin;
+    uint32_t bBottom = bufYMin + bufHeight - margin;
+
+    uint32_t defaultCropOrigin[] = {std::max(aLeft, bLeft), std::max(aTop, bTop)};
+    uint32_t defaultCropSize[] = {std::min(aRight, bRight) - defaultCropOrigin[0],
+            std::min(aBottom, bBottom) - defaultCropOrigin[1]};
+
+    BAIL_IF_INVALID_R(writer->addEntry(TAG_DEFAULTCROPORIGIN, 2, defaultCropOrigin,
+            TIFF_IFD_0), env, TAG_DEFAULTCROPORIGIN, writer);
+    BAIL_IF_INVALID_R(writer->addEntry(TAG_DEFAULTCROPSIZE, 2, defaultCropSize,
+            TIFF_IFD_0), env, TAG_DEFAULTCROPSIZE, writer);
+
+    return OK;
+}
+
+static bool validateDngHeader(JNIEnv* env, TiffWriter* writer,
+        const CameraMetadata& characteristics, jint width, jint height) {
     // TODO: handle lens shading map, etc. conversions for other raw buffer sizes.
-    uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, (hasThumbnail) ? TIFF_IFD_SUB1 :
-            TIFF_IFD_0)->getData<uint32_t>());
-    uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, (hasThumbnail) ? TIFF_IFD_SUB1 :
-            TIFF_IFD_0)->getData<uint32_t>());
-
-    if (width < 0 || metadataWidth != static_cast<uint32_t>(width)) {
+    if (width <= 0) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
-                        "Metadata width %d doesn't match image width %d", metadataWidth, width);
+                        "Image width %d is invalid", width);
         return false;
     }
 
-    if (height < 0 || metadataHeight != static_cast<uint32_t>(height)) {
+    if (height <= 0) {
         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
-                        "Metadata height %d doesn't match image height %d",
-                        metadataHeight, height);
+                        "Image height %d is invalid", height);
+        return false;
+    }
+
+    camera_metadata_ro_entry preCorrectionEntry =
+            characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+    camera_metadata_ro_entry pixelArrayEntry =
+            characteristics.find(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE);
+
+    int pWidth = static_cast<int>(pixelArrayEntry.data.i32[0]);
+    int pHeight = static_cast<int>(pixelArrayEntry.data.i32[1]);
+    int cWidth = static_cast<int>(preCorrectionEntry.data.i32[2]);
+    int cHeight = static_cast<int>(preCorrectionEntry.data.i32[3]);
+
+    bool matchesPixelArray = (pWidth == width && pHeight == height);
+    bool matchesPreCorrectionArray = (cWidth == width && cHeight == height);
+
+    if (matchesPixelArray) {
+        if (calculateAndSetCrop(env, characteristics, 0, 0, static_cast<uint32_t>(pWidth),
+                static_cast<uint32_t>(pHeight), writer) != OK) {
+            return false;
+        }
+    } else if (matchesPreCorrectionArray) {
+        if (calculateAndSetCrop(env, characteristics,
+                static_cast<uint32_t>(preCorrectionEntry.data.i32[0]),
+                static_cast<uint32_t>(preCorrectionEntry.data.i32[1]),
+                static_cast<uint32_t>(preCorrectionEntry.data.i32[2]),
+                static_cast<uint32_t>(preCorrectionEntry.data.i32[3]), writer) != OK) {
+            return false;
+        }
+    } else {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", \
+                        "Image dimensions (w=%d,h=%d) are invalid, must match either the pixel "
+                        "array size (w=%d, h=%d) or the pre-correction array size (w=%d, h=%d)",
+                        width, height, pWidth, pHeight, cWidth, cHeight);
         return false;
     }
 
@@ -854,7 +937,7 @@
         return;
     }
 
-    sp<NativeContext> nativeContext = new NativeContext();
+    sp<NativeContext> nativeContext = new NativeContext(characteristics, results);
     TiffWriter* writer = nativeContext->getWriter();
 
     writer->addIfd(TIFF_IFD_0);
@@ -906,7 +989,7 @@
     {
         // Set dimensions
         camera_metadata_entry entry =
-                characteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+                characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
         BAIL_IF_EMPTY(entry, env, TAG_IMAGEWIDTH, writer);
         uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
         uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
@@ -1356,16 +1439,16 @@
     }
 
     {
-        // Setup default crop + crop origin tags
-        uint32_t margin = 8; // Default margin recommended by Adobe for interpolation.
-        uint32_t dimensionLimit = 128; // Smallest image dimension crop margin from.
-        if (imageWidth >= dimensionLimit && imageHeight >= dimensionLimit) {
-            uint32_t defaultCropOrigin[] = {margin, margin};
-            uint32_t defaultCropSize[] = {imageWidth - 2 * margin, imageHeight - 2 * margin};
-            BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPORIGIN, 2, defaultCropOrigin,
-                    TIFF_IFD_0), env, TAG_DEFAULTCROPORIGIN, writer);
-            BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPSIZE, 2, defaultCropSize,
-                    TIFF_IFD_0), env, TAG_DEFAULTCROPSIZE, writer);
+        // Set dimensions
+        camera_metadata_entry entry =
+                characteristics.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+        BAIL_IF_EMPTY(entry, env, TAG_DEFAULTCROPSIZE, writer);
+        uint32_t xmin = static_cast<uint32_t>(entry.data.i32[0]);
+        uint32_t ymin = static_cast<uint32_t>(entry.data.i32[1]);
+        uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
+        uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
+        if (calculateAndSetCrop(env, characteristics, xmin, ymin, width, height, writer) != OK) {
+            return;
         }
     }
 
@@ -1874,7 +1957,7 @@
     }
 
     // Validate DNG header
-    if (!validateDngHeader(env, writer, width, height)) {
+    if (!validateDngHeader(env, writer, *(context->getCharacteristics()), width, height)) {
         return;
     }
 
@@ -1978,7 +2061,7 @@
     }
 
     // Validate DNG header
-    if (!validateDngHeader(env, writer, width, height)) {
+    if (!validateDngHeader(env, writer, *(context->getCharacteristics()), width, height)) {
         return;
     }
 
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 2ee9283..0f5ba83f 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -230,9 +230,11 @@
 
 static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) {
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
-    const status_t err = parcel->writeInt32(val);
-    if (err != NO_ERROR) {
-        signalExceptionForError(env, clazz, err);
+    if (parcel != NULL) {
+        const status_t err = parcel->writeInt32(val);
+        if (err != NO_ERROR) {
+            signalExceptionForError(env, clazz, err);
+        }
     }
 }
 
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/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f9b41a93..9637cf5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -349,20 +349,6 @@
         android:description="@string/permdesc_writeContacts"
         android:protectionLevel="dangerous" />
 
-    <!-- @deprecated No longer enforced. This was last enforced in API version 22. -->
-    <permission android:name="android.permission.READ_PROFILE"
-        android:permissionGroup="android.permission-group.CONTACTS"
-        android:label="@string/permlab_readProfile"
-        android:description="@string/permdesc_readProfile"
-        android:protectionLevel="dangerous" />
-
-    <!-- @deprecated No longer enforced. This was last enforced in API version 22. -->
-    <permission android:name="android.permission.WRITE_PROFILE"
-        android:permissionGroup="android.permission-group.CONTACTS"
-        android:label="@string/permlab_writeProfile"
-        android:description="@string/permdesc_writeProfile"
-        android:protectionLevel="dangerous" />
-
     <!-- ====================================================================== -->
     <!-- Permissions for accessing user's calendar                              -->
     <!-- ====================================================================== -->
@@ -511,42 +497,6 @@
         android:description="@string/permdesc_sdcardWrite"
         android:protectionLevel="dangerous" />
 
-    <!-- =============================================================== -->
-    <!-- Permissions for accessing social info                           -->
-    <!-- =============================================================== -->
-    <eat-comment />
-
-    <!-- Used for permissions that provide access to the user's social connections,
-         such as contacts, call logs, social stream, etc.  This includes
-         both reading and writing of this data (which should generally be
-         expressed as two distinct permissions). -->
-
-    <permission-group android:name="android.permission-group.SOCIAL_INFO"
-        android:label="@string/permgrouplab_socialInfo"
-        android:icon="@drawable/perm_group_social_info"
-        android:description="@string/permgroupdesc_socialInfo"
-        android:permissionGroupFlags="personalInfo"
-        android:priority="1200" />
-
-    <!-- Allows an application to read from the user's social stream.
-         @deprecated This functionality will be unsupported in the future; cursors returned
-         will be empty. Please do not use. -->
-    <permission android:name="android.permission.READ_SOCIAL_STREAM"
-        android:permissionGroup="android.permission-group.SOCIAL_INFO"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_readSocialStream"
-        android:description="@string/permdesc_readSocialStream" />
-
-    <!-- Allows an application to write (but not read) the user's
-         social stream data.
-         @deprecated This functionality will be unsupported in the future; cursors returned
-         will be empty. Please do not use. -->
-    <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
-        android:permissionGroup="android.permission-group.SOCIAL_INFO"
-        android:protectionLevel="dangerous"
-        android:label="@string/permlab_writeSocialStream"
-        android:description="@string/permdesc_writeSocialStream" />
-
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device location                          -->
     <!-- ====================================================================== -->
@@ -741,7 +691,41 @@
         android:protectionLevel="normal" />
 
     <!-- ====================================================================== -->
-    <!-- INSTALLTIME PERMISSIONS                                                -->
+    <!-- REMOVED PERMISSIONS                                                    -->
+    <!-- ====================================================================== -->
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.READ_PROFILE"
+        android:protectionLevel="normal"
+        android:permissionFlags="hide"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.WRITE_PROFILE"
+        android:protectionLevel="normal"
+        android:permissionFlags="hide"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.READ_SOCIAL_STREAM"
+        android:protectionLevel="normal"
+        android:permissionFlags="hide"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
+        android:protectionLevel="normal"
+        android:permissionFlags="hide"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.READ_USER_DICTIONARY"
+        android:protectionLevel="normal"
+        android:permissionFlags="hide"/>
+
+    <!-- @hide We need to keep this around for backwards compatibility -->
+    <permission android:name="android.permission.WRITE_USER_DICTIONARY"
+        android:protectionLevel="normal"
+        android:permissionFlags="hide"/>
+
+    <!-- ====================================================================== -->
+    <!-- INSTALL PERMISSIONS                                                    -->
     <!-- ====================================================================== -->
 
     <!-- ================================== -->
@@ -780,36 +764,6 @@
         android:protectionLevel="signature|system" />
 
     <!-- =============================================================== -->
-    <!-- Permissions for accessing the user dictionary-->
-    <!-- =============================================================== -->
-    <eat-comment />
-
-    <!-- Used for permissions that provide access to the user
-         calendar to create / view events.-->
-    <permission-group android:name="android.permission-group.USER_DICTIONARY"
-        android:label="@string/permgrouplab_dictionary"
-        android:icon="@drawable/perm_group_user_dictionary"
-        android:description="@string/permgroupdesc_dictionary"
-        android:permissionGroupFlags="personalInfo"
-        android:priority="1100" />
-
-    <!-- Allows an application to read the user dictionary. This should
-         really only be required by an IME, or a dictionary editor like
-         the Settings app. -->
-    <permission android:name="android.permission.READ_USER_DICTIONARY"
-        android:permissionGroup="android.permission-group.USER_DICTIONARY"
-        android:label="@string/permlab_readDictionary"
-        android:description="@string/permdesc_readDictionary"
-        android:protectionLevel="dangerous"/>
-
-    <!-- Allows an application to write to the user dictionary. -->
-    <permission android:name="android.permission.WRITE_USER_DICTIONARY"
-        android:permissionGroup="android.permission-group.USER_DICTIONARY"
-        android:label="@string/permlab_writeDictionary"
-        android:description="@string/permdesc_writeDictionary"
-        android:protectionLevel="normal"/>
-
-    <!-- =============================================================== -->
     <!-- Permissions for setting the device alarm                        -->
     <!-- =============================================================== -->
     <eat-comment />
@@ -2090,7 +2044,7 @@
          <p>Declaring the permission implies intention to use the API and the user of the
          device can grant permission through the Settings application. -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
-        android:protectionLevel="signature|development|appop" />
+        android:protectionLevel="signature|system|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <!-- @hide Allows an application to change the app idle state of an app.
diff --git a/core/res/res/drawable-hdpi/perm_group_storage.png b/core/res/res/drawable-hdpi/perm_group_storage.png
deleted file mode 100644
index 598e1cc..0000000
--- a/core/res/res/drawable-hdpi/perm_group_storage.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_user_dictionary.png b/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
deleted file mode 100644
index 62fbcdc..0000000
--- a/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
deleted file mode 100644
index c62dd4c..0000000
--- a/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_storage.png b/core/res/res/drawable-mdpi/perm_group_storage.png
deleted file mode 100644
index b7a06fb..0000000
--- a/core/res/res/drawable-mdpi/perm_group_storage.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_user_dictionary.png b/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
deleted file mode 100644
index a303dc1..0000000
--- a/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
deleted file mode 100644
index 2fc4056..0000000
--- a/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_storage.png b/core/res/res/drawable-xhdpi/perm_group_storage.png
deleted file mode 100644
index a2d4d5e..0000000
--- a/core/res/res/drawable-xhdpi/perm_group_storage.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png b/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
deleted file mode 100644
index 35d7d5f..0000000
--- a/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
deleted file mode 100644
index 74e25ac..0000000
--- a/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary.png b/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary.png
deleted file mode 100644
index 8c2cd17..0000000
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary_write.png b/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary_write.png
deleted file mode 100644
index 121d6cf..0000000
--- a/core/res/res/drawable-xxhdpi/ic_perm_group_user_dictionary_write.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_storage.png b/core/res/res/drawable-xxhdpi/perm_group_storage.png
deleted file mode 100644
index 837211e..0000000
--- a/core/res/res/drawable-xxhdpi/perm_group_storage.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_user_dictionary.png b/core/res/res/drawable-xxhdpi/perm_group_user_dictionary.png
deleted file mode 100644
index 5b6ea3b..0000000
--- a/core/res/res/drawable-xxhdpi/perm_group_user_dictionary.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.png
deleted file mode 100644
index d92e719..0000000
--- a/core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_storage.png b/core/res/res/drawable-xxxhdpi/perm_group_storage.png
deleted file mode 100644
index 918b3ed..0000000
--- a/core/res/res/drawable-xxxhdpi/perm_group_storage.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_user_dictionary.png b/core/res/res/drawable-xxxhdpi/perm_group_user_dictionary.png
deleted file mode 100644
index 32942ca..0000000
--- a/core/res/res/drawable-xxxhdpi/perm_group_user_dictionary.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-xxxhdpi/perm_group_user_dictionary_write.png
deleted file mode 100644
index 343551f..0000000
--- a/core/res/res/drawable-xxxhdpi/perm_group_user_dictionary_write.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml
index 11078d3..65da1f1 100644
--- a/core/res/res/drawable/perm_group_storage.xml
+++ b/core/res/res/drawable/perm_group_storage.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="24dp"
+        android:height="24dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
     <path
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f31c1d6..3cb4d7c 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -231,6 +231,9 @@
              may cost the user money.  Such permissions may be highlighted
              when shown to the user with this additional information.  -->
         <flag name="costsMoney" value="0x0001" />
+        <!-- Additional flag from base permission type: this permission is hidden
+             and should not show in the UI. -->
+        <flag name="hide" value="0x2" />
     </attr>
 
     <!-- Specified the name of a group that this permission is associated
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/values/strings.xml b/core/res/res/values/strings.xml
index ea0d349..246e43a33 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -554,11 +554,6 @@
     <string name="permgroupdesc_location">access this device\'s location</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_socialInfo">Your social information</string>
-    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_socialInfo">Direct access to information about your contacts and social connections.</string>
-
-    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_calendar">Calendar</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_calendar">access your calendar</string>
@@ -573,16 +568,6 @@
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_storage">access photos, media, and files on your device</string>
 
-    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_dictionary">User Dictionary</string>
-    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_dictionary">Read or write words in user dictionary.</string>
-
-    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_bookmarks">Bookmarks and History</string>
-    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_bookmarks">Direct access to bookmarks and browser history.</string>
-
     <!-- Title of a category of application permissioncds, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_microphone">Microphone</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
@@ -901,23 +886,6 @@
     <string name="permdesc_writeCallLog" product="default">Allows the app to modify your phone\'s call log, including data about incoming and outgoing calls.
         Malicious apps may use this to erase or modify your call log.</string>
 
-
-    <!-- Title of the read profile permission, listed so the user can decide whether to allow the application to read the user's personal profile data. [CHAR LIMIT=30] -->
-    <string name="permlab_readProfile">read your own contact card</string>
-    <!-- Description of the read profile permission, listed so the user can decide whether to allow the application to read the user's personal profile data. [CHAR LIMIT=NONE] -->
-    <string name="permdesc_readProfile" product="default">Allows the app to read
-     personal profile information stored on your device, such as your name and
-     contact information. This means the app can identify you and may send your
-     profile information to others.</string>
-
-    <!-- Title of the write profile permission, listed so the user can decide whether to allow the application to write to the user's personal profile data. [CHAR LIMIT=30] -->
-    <string name="permlab_writeProfile">modify your own contact card</string>
-    <!-- Description of the write profile permission, listed so the user can decide whether to allow the application to write to the user's personal profile data. [CHAR LIMIT=NONE] -->
-    <string name="permdesc_writeProfile" product="default">Allows the app to
-      change or add to personal profile information stored on your device, such
-      as your name and contact information.  This means the app can identify you
-      and may send your profile information to others.</string>
-
     <!-- Title of the body sensors permission, listed so the user can decide whether to allow the application to access body sensor data. [CHAR LIMIT=30] -->
     <string name="permlab_bodySensors">body sensors (like heart rate monitors)
     </string>
@@ -925,23 +893,6 @@
     <string name="permdesc_bodySensors" product="default">Allows the app to access data from sensors
     that monitor your physical condition, such as your heart rate.</string>
 
-    <!-- Title of the read social stream permission, listed so the user can decide whether to allow the application to read information from the user's social stream. [CHAR LIMIT=30] -->
-    <string name="permlab_readSocialStream" product="default">read your social stream</string>
-    <string name="permdesc_readSocialStream" product="default">Allows the app
-      to access and sync social updates from you and your friends. Be careful
-      when sharing information -- this allows the app to read communications
-      between you and your friends on social networks, regardless of
-      confidentiality. Note: this permission may not be enforced on all social
-      networks.</string>
-
-    <!-- Title of the write social stream permission, listed so the user can decide whether to allow the application to write information to the user's social stream. [CHAR LIMIT=30] -->
-    <string name="permlab_writeSocialStream" product="default">write to your social stream</string>
-    <string name="permdesc_writeSocialStream" product="default">Allows the app to
-     display social updates from your friends.  Be careful when sharing
-     information -- this allows the app to produce messages that may appear to
-     come from a friend. Note: this permission may not be enforced on all social
-     networks.</string>
-
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readCalendar">read calendar events plus confidential information</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -1285,18 +1236,6 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_readSyncStats">Allows an app to read the sync stats for an account, including the history of sync events and how much data is synced. </string>
 
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_readDictionary">read terms you added to the dictionary</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_readDictionary">Allows the app to read all words,
-       names and phrases that the user may have stored in the user dictionary.</string>
-
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_writeDictionary">add words to user-defined dictionary</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_writeDictionary">Allows the app to write new words into the
-      user dictionary.</string>
-
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
     <string name="permlab_sdcardRead" product="nosdcard">read the contents of your USB storage</string>
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/docs/html/about/versions/android-4.0.3.jd b/docs/html/about/versions/android-4.0.3.jd
index 5fa8547..4c2ccb9 100644
--- a/docs/html/about/versions/android-4.0.3.jd
+++ b/docs/html/about/versions/android-4.0.3.jd
@@ -78,19 +78,19 @@
 stream along with photos for each.</p>
 
 <p>The database table that contains an individual contact’s social stream is
-defined by {@link android.provider.ContactsContract.StreamItems}, the Uri for
+defined by android.provider.ContactsContract.StreamItems, the Uri for
 which is nested within the {@link android.provider.ContactsContract.RawContacts}
 directory to which the stream items belong. Each social stream table includes
 several columns for metadata about each stream item, such as an icon
 representing the source (an avatar), a label for the item, the primary text
 content, comments about the item (such as responses from other people), and
 more. Photos associated with a stream are stored in another table, defined by
-{@link android.provider.ContactsContract.StreamItemPhotos}, which is available
-as a sub-directory of the {@link android.provider.ContactsContract.StreamItems}
+android.provider.ContactsContract.StreamItemPhotos, which is available
+as a sub-directory of the android.provider.ContactsContract.StreamItems
 Uri.</p>
 
-<p>See {@link android.provider.ContactsContract.StreamItems} and
-{@link android.provider.ContactsContract.StreamItemPhotos} for more information.</p>
+<p>See android.provider.ContactsContract.StreamItems and
+android.provider.ContactsContract.StreamItemPhotos for more information.</p>
 
 <p>To read or write social stream items for a contact, an application must
 request permission from the user by declaring <code>&lt;uses-permission
@@ -272,8 +272,8 @@
 
 <p>The following are new permissions:</p>
 <ul>
-<li>{@link android.Manifest.permission#READ_SOCIAL_STREAM} and 
-{@link android.Manifest.permission#WRITE_SOCIAL_STREAM}: Allow a sync
+<li>android.Manifest.permission#READ_SOCIAL_STREAM and
+android.Manifest.permission#WRITE_SOCIAL_STREAM: Allow a sync
 adapter to read and write social stream data to a contact in the shared
 Contacts Provider.</li>
 </ul>
diff --git a/docs/html/about/versions/android-4.0.jd b/docs/html/about/versions/android-4.0.jd
index 6c4ccb4..cc1d1c7 100644
--- a/docs/html/about/versions/android-4.0.jd
+++ b/docs/html/about/versions/android-4.0.jd
@@ -108,9 +108,9 @@
 the table at {@link android.provider.ContactsContract.Profile#CONTENT_RAW_CONTACTS_URI}. Raw
 contacts in this table are then aggregated into the single user-visible profile labeled "Me".</p>
 
-<p>Adding a new raw contact for the profile requires the {@link
-android.Manifest.permission#WRITE_PROFILE} permission. Likewise, in order to read from the profile
-table, you must request the {@link android.Manifest.permission#READ_PROFILE} permission. However,
+<p>Adding a new raw contact for the profile requires the
+android.Manifest.permission#WRITE_PROFILE permission. Likewise, in order to read from the profile
+table, you must request the android.Manifest.permission#READ_PROFILE permission. However,
 most apps should not need to read the user profile, even when contributing data to the
 profile. Reading the user profile is a sensitive permission and you should expect users to be
 skeptical of apps that request it.</p>
@@ -1638,9 +1638,9 @@
 android.service.textservice.SpellCheckerService} must require this permission for itself.</li>
 <li>{@link android.Manifest.permission#BIND_VPN_SERVICE}: A service that implements {@link
 android.net.VpnService} must require this permission for itself.</li>
-<li>{@link android.Manifest.permission#READ_PROFILE}: Provides read access to the {@link
+<li>android.Manifest.permission#READ_PROFILE: Provides read access to the {@link
 android.provider.ContactsContract.Profile} provider.</li>
-<li>{@link android.Manifest.permission#WRITE_PROFILE}: Provides write access to the {@link
+<li>android.Manifest.permission#WRITE_PROFILE: Provides write access to the {@link
 android.provider.ContactsContract.Profile} provider.</li>
 </ul>
 
diff --git a/docs/html/about/versions/android-4.1.jd b/docs/html/about/versions/android-4.1.jd
index 76b90ac..f8770fa 100644
--- a/docs/html/about/versions/android-4.1.jd
+++ b/docs/html/about/versions/android-4.1.jd
@@ -871,7 +871,7 @@
 automatically get read access as well.  There is a new developer option to turn on read access
 restriction, for developers to test their applications against how Android will behave in the
 future.</dd>
-  <dt>{@link android.Manifest.permission#READ_USER_DICTIONARY}</dt>
+  <dt>android.Manifest.permission.READ_USER_DICTIONARY</dt>
     <dd>Allows an application to read the user dictionary. This should only be required by an
 IME, or a dictionary editor like the Settings app.</dd>
   <dt>{@link android.Manifest.permission#READ_CALL_LOG}</dt>
@@ -879,7 +879,7 @@
       incoming and outgoing calls.</dd>
   <dt>{@link android.Manifest.permission#WRITE_CALL_LOG}</dt>
     <dd>Allows an application to modify the system's call log stored on your phone</dd>
-  <dt>{@link android.Manifest.permission#WRITE_USER_DICTIONARY}</dt>
+  <dt>android.Manifest.permission.WRITE_USER_DICTIONARY</dt>
     <dd>Allows an application to write to the user's word dictionary.</dd>
 </dl>
 
diff --git a/docs/html/guide/topics/providers/contacts-provider.jd b/docs/html/guide/topics/providers/contacts-provider.jd
index e3b998a..2b14558 100644
--- a/docs/html/guide/topics/providers/contacts-provider.jd
+++ b/docs/html/guide/topics/providers/contacts-provider.jd
@@ -57,7 +57,7 @@
     <li>{@link android.provider.ContactsContract.Contacts}</li>
     <li>{@link android.provider.ContactsContract.RawContacts}</li>
     <li>{@link android.provider.ContactsContract.Data}</li>
-    <li>{@link android.provider.ContactsContract.StreamItems}</li>
+    <li>android.provider.ContactsContract.StreamItems</li>
 </ol>
 <h2>Related Samples</h2>
 <ol>
@@ -606,13 +606,13 @@
     Access to the user profile requires special permissions. In addition to the
     {@link android.Manifest.permission#READ_CONTACTS} and
     {@link android.Manifest.permission#WRITE_CONTACTS} permissions needed to read and write, access
-    to the user profile requires the {@link android.Manifest.permission#READ_PROFILE} and
-    {@link android.Manifest.permission#WRITE_PROFILE} permissions for read and write access,
+    to the user profile requires the android.Manifest.permission#READ_PROFILE and
+    android.Manifest.permission#WRITE_PROFILE permissions for read and write access,
     respectively.
 </p>
 <p>
     Remember that you should consider a user's profile to be sensitive. The permission
-    {@link android.Manifest.permission#READ_PROFILE} allows you to access the device user's
+    android.Manifest.permission#READ_PROFILE allows you to access the device user's
     personally-identifying data. Make sure to tell the user why
     you need user profile access permissions in the description of your application.
 </p>
@@ -1826,8 +1826,8 @@
     </dl>
 <h2 id="SocialStream">Social Stream Data</h2>
 <p>
-    The {@link android.provider.ContactsContract.StreamItems} and
-    {@link android.provider.ContactsContract.StreamItemPhotos} tables
+    The android.provider.ContactsContract.StreamItems and
+    android.provider.ContactsContract.StreamItemPhotos tables
     manage incoming data from social networks. You can write a sync adapter that adds stream data
     from your own network to these tables, or you can read stream data from these tables and
     display it in your own application, or both. With these features, your social networking
@@ -1836,7 +1836,7 @@
 <h3 id="StreamText">Social stream text</h3>
 <p>
     Stream items are always associated with a raw contact. The
-    {@link android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} links to the
+    android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID links to the
     <code>_ID</code> value for the raw contact. The account type and account name of the raw
     contact are also stored in the stream item row.
 </p>
@@ -1845,14 +1845,14 @@
 </p>
 <dl>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE}
+        android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE
     </dt>
     <dd>
         <strong>Required.</strong> The user's account type for the raw contact associated with this
         stream item. Remember to set this value when you insert a stream item.
     </dd>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME}
+        android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME
     </dt>
     <dd>
         <strong>Required.</strong> The user's account name for the raw contact associated with this
@@ -1866,30 +1866,30 @@
         insert a stream item:
         <ul>
             <li>
-                {@link android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}: The
-                {@link android.provider.BaseColumns#_ID} value of the contact that this stream
+                android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID: The
+                android.provider.BaseColumns#_ID value of the contact that this stream
                 item is associated with.
             </li>
             <li>
-                {@link android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}: The
-                {@link android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} value of the
+                android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY: The
+                android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY value of the
                 contact this stream item is associated with.
             </li>
             <li>
-                {@link android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}: The
-                {@link android.provider.BaseColumns#_ID} value of the raw contact that this stream
+                android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID: The
+                android.provider.BaseColumns#_ID value of the raw contact that this stream
                 item is associated with.
             </li>
         </ul>
     </dd>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemsColumns#COMMENTS}
+        android.provider.ContactsContract.StreamItemsColumns#COMMENTS
     </dt>
     <dd>
         Optional. Stores summary information that you can display at the beginning of a stream item.
     </dd>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemsColumns#TEXT}
+        android.provider.ContactsContract.StreamItemsColumns#TEXT
     </dt>
     <dd>
         The text of the stream item, either the content that was posted by the source of the item,
@@ -1899,7 +1899,7 @@
         ellipsize long content, but it will try to avoid breaking tags.
     </dd>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}
+        android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP
     </dt>
     <dd>
         A text string containing the time the stream item was inserted or updated, in the form
@@ -1910,42 +1910,42 @@
 </dl>
 <p>
     To display identifying information for your stream items, use the
-    {@link android.provider.ContactsContract.StreamItemsColumns#RES_ICON},
-    {@link android.provider.ContactsContract.StreamItemsColumns#RES_LABEL}, and
-    {@link android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE} to link to resources
+    android.provider.ContactsContract.StreamItemsColumns#RES_ICON,
+    android.provider.ContactsContract.StreamItemsColumns#RES_LABEL, and
+    android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE to link to resources
     in your application.
 </p>
 <p>
-    The {@link android.provider.ContactsContract.StreamItems} table also contains the columns
-    {@link android.provider.ContactsContract.StreamItemsColumns#SYNC1} through
-    {@link android.provider.ContactsContract.StreamItemsColumns#SYNC4} for the exclusive use of
+    The android.provider.ContactsContract.StreamItems table also contains the columns
+    android.provider.ContactsContract.StreamItemsColumns#SYNC1 through
+    android.provider.ContactsContract.StreamItemsColumns#SYNC4 for the exclusive use of
     sync adapters.
 </p>
 <h3 id="StreamPhotos">Social stream photos</h3>
 <p>
-   The {@link android.provider.ContactsContract.StreamItemPhotos} table stores photos associated
+   The android.provider.ContactsContract.StreamItemPhotos table stores photos associated
    with a stream item. The table's
-   {@link android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID} column
+   android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID column
    links to values in the {@link android.provider.BaseColumns#_ID} column of
-   {@link android.provider.ContactsContract.StreamItems} table. Photo references are stored in the
+   android.provider.ContactsContract.StreamItems table. Photo references are stored in the
    table in these columns:
 </p>
 <dl>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemPhotos#PHOTO} column (a BLOB).
+        android.provider.ContactsContract.StreamItemPhotos#PHOTO column (a BLOB).
     </dt>
     <dd>
         A binary representation of the photo, resized by the provider for storage and display.
         This column is available for backwards compatibility with previous versions of the Contacts
         Provider that used it for storing photos. However, in the current version
         you should not use this column to store photos. Instead, use
-        either {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} or
-        {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} (both of
+        either android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID or
+        android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI (both of
         which are described in the following points) to store photos in a file. This column now
         contains a thumbnail of the photo, which is available for reading.
     </dd>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID}
+        android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID
     </dt>
     <dd>
         A numeric identifier of a photo for a raw contact. Append this value to the constant
@@ -1955,7 +1955,7 @@
         openAssetFileDescriptor()} to get a handle to the photo file.
     </dd>
     <dt>
-        {@link android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI}
+        android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI
     </dt>
     <dd>
         A content URI pointing directly to the photo file for the photo represented by this row.
@@ -1970,27 +1970,27 @@
     <ul>
         <li>
             These tables require additional access permissions. To read from them, your application
-            must have the permission {@link android.Manifest.permission#READ_SOCIAL_STREAM}. To
+            must have the permission android.Manifest.permission#READ_SOCIAL_STREAM. To
             modify them, your application must have the permission
-            {@link android.Manifest.permission#WRITE_SOCIAL_STREAM}.
+            android.Manifest.permission#WRITE_SOCIAL_STREAM.
         </li>
         <li>
-            For the {@link android.provider.ContactsContract.StreamItems} table, the number of rows
+            For the android.provider.ContactsContract.StreamItems table, the number of rows
             stored for each raw contact is limited. Once this limit is reached,
             the Contacts Provider makes space for new stream item rows by automatically deleting
             the rows having the oldest
-            {@link android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}. To get the
+            android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP. To get the
             limit, issue a query to the content URI
-            {@link android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}. You can leave
+            android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI. You can leave
             all the arguments other than the content URI set to <code>null</code>. The query
             returns a Cursor containing a single row, with the single column
-            {@link android.provider.ContactsContract.StreamItems#MAX_ITEMS}.
+            android.provider.ContactsContract.StreamItems#MAX_ITEMS.
         </li>
     </ul>
 
 <p>
-    The class {@link android.provider.ContactsContract.StreamItems.StreamItemPhotos} defines a
-    sub-table of {@link android.provider.ContactsContract.StreamItemPhotos} containing the photo
+    The class android.provider.ContactsContract.StreamItems.StreamItemPhotos defines a
+    sub-table of android.provider.ContactsContract.StreamItemPhotos containing the photo
     rows for a single stream item.
 </p>
 <h3 id="SocialStreamInteraction">Social stream interactions</h3>
@@ -2003,8 +2003,8 @@
         <li>
             By syncing your social networking service to the Contacts Provider with a sync
             adapter, you can retrieve recent activity for a user's contacts and store it in
-            the {@link android.provider.ContactsContract.StreamItems} and
-            {@link android.provider.ContactsContract.StreamItemPhotos} tables for later use.
+            the android.provider.ContactsContract.StreamItems and
+            android.provider.ContactsContract.StreamItemPhotos tables for later use.
         </li>
         <li>
             Besides regular synchronization, you can trigger your sync adapter to retrieve
@@ -2356,6 +2356,6 @@
 </p>
 <p>
     Social stream data for a person may also include photos. These are stored in the
-    {@link android.provider.ContactsContract.StreamItemPhotos} table, which is described in more
+    android.provider.ContactsContract.StreamItemPhotos table, which is described in more
     detail in the section <a href="#StreamPhotos">Social stream photos</a>.
 </p>
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index dcccf35..2bbbff3 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -67,4 +67,38 @@
          */
         public final int nativeInt;
     }
+
+    /**
+     * @hide
+     */
+    public static final int modeToInt(Mode mode) {
+        return mode.nativeInt;
+    }
+
+    /**
+     * @hide
+     */
+    public static final Mode intToMode(int val) {
+        switch (val) {
+            default:
+            case  0: return Mode.CLEAR;
+            case  1: return Mode.SRC;
+            case  2: return Mode.DST;
+            case  3: return Mode.SRC_OVER;
+            case  4: return Mode.DST_OVER;
+            case  5: return Mode.SRC_IN;
+            case  6: return Mode.DST_IN;
+            case  7: return Mode.SRC_OUT;
+            case  8: return Mode.DST_OUT;
+            case  9: return Mode.SRC_ATOP;
+            case 10: return Mode.DST_ATOP;
+            case 11: return Mode.XOR;
+            case 16: return Mode.DARKEN;
+            case 17: return Mode.LIGHTEN;
+            case 13: return Mode.MULTIPLY;
+            case 14: return Mode.SCREEN;
+            case 12: return Mode.ADD;
+            case 15: return Mode.OVERLAY;
+        }
+    }
 }
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index f059727..fcd7f63 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -362,11 +362,6 @@
         invalidateSelf();
     }
 
-    @Override
-    public boolean isDither() {
-        return mBitmapState.mPaint.isDither();
-    }
-
     /**
      * Indicates the repeat behavior of this drawable on the X axis.
      *
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 7af78a7..32af59a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -269,26 +269,16 @@
     }
 
     /**
-     * Set to true to have the drawable dither its colors when drawn to a device
-     * with fewer than 8-bits per color component.
+     * Set to true to have the drawable dither its colors when drawn to a
+     * device with fewer than 8-bits per color component.
      *
-     * <p>This can improve the look on those devices, but can also slow down
-     * the drawing a little.</p>
-     *
-     * @see #isDither()
      * @see android.graphics.Paint#setDither(boolean);
+     * @deprecated This property is ignored.
      */
+    @Deprecated
     public void setDither(boolean dither) {}
 
     /**
-     * @return whether this drawable dithers its colors
-     * @see #setDither(boolean)
-     */
-    public boolean isDither() {
-        return false;
-    }
-
-    /**
      * Set to true to have the drawable filter its bitmaps with bilinear
      * sampling when they are scaled or rotated.
      *
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 1759f53..b344b86 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,11 +167,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mDrawableContainerState.mDither;
-    }
-
-    @Override
     public void setColorFilter(ColorFilter colorFilter) {
         mDrawableContainerState.mHasColorFilter = true;
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 626991d..a11b2cd 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -826,11 +826,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mGradientState.mDither;
-    }
-
-    @Override
     public ColorFilter getColorFilter() {
         return mColorFilter;
     }
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 85db6a1..7c9b30b 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -16,13 +16,16 @@
 
 package android.graphics.drawable;
 
+import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.content.res.ColorStateList;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.PorterDuff;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -67,6 +70,10 @@
 
     private final int mType;
 
+    private ColorStateList mTintList;
+    static final PorterDuff.Mode DEFAULT_TINT_MODE = Drawable.DEFAULT_TINT_MODE; // SRC_IN
+    private PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
+
     // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed
     // based on the value of mType.
 
@@ -109,6 +116,10 @@
         return (Bitmap) mObj1;
     }
 
+    private void setBitmap(Bitmap b) {
+        mObj1 = b;
+    }
+
     /**
      * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon.
      * @hide
@@ -254,6 +265,19 @@
      * @return A fresh instance of a drawable for this image, yours to keep.
      */
     public Drawable loadDrawable(Context context) {
+        final Drawable result = loadDrawableInner(context);
+        if (result != null && (mTintList != null || mTintMode != DEFAULT_TINT_MODE)) {
+            result.mutate();
+            result.setTintList(mTintList);
+            result.setTintMode(mTintMode);
+        }
+        return result;
+    }
+
+    /**
+     * Do the heavy lifting of loading the drawable, but stop short of applying any tint.
+     */
+    private Drawable loadDrawableInner(Context context) {
         switch (mType) {
             case TYPE_BITMAP:
                 return new BitmapDrawable(context.getResources(), getBitmap());
@@ -347,6 +371,16 @@
     }
 
     /**
+     * Puts the memory used by this instance into Ashmem memory, if possible.
+     * @hide
+     */
+    public void convertToAshmem() {
+        if (mType == TYPE_BITMAP && getBitmap().isMutable()) {
+            setBitmap(getBitmap().createAshmemBitmap());
+        }
+    }
+
+    /**
      * Writes a serialized version of an Icon to the specified stream.
      *
      * @param stream The stream on which to serialize the Icon.
@@ -466,7 +500,7 @@
             throw new IllegalArgumentException("Bitmap must not be null.");
         }
         final Icon rep = new Icon(TYPE_BITMAP);
-        rep.mObj1 = bits;
+        rep.setBitmap(bits);
         return rep;
     }
 
@@ -518,6 +552,38 @@
     }
 
     /**
+     * Store a color to use whenever this Icon is drawn.
+     *
+     * @param tint a color, as in {@link Drawable#setTint(int)}
+     * @return this same object, for use in chained construction
+     */
+    public Icon setTint(@ColorInt int tint) {
+        return setTintList(ColorStateList.valueOf(tint));
+    }
+
+    /**
+     * Store a color to use whenever this Icon is drawn.
+     *
+     * @param tintList as in {@link Drawable#setTintList(ColorStateList)}, null to remove tint
+     * @return this same object, for use in chained construction
+     */
+    public Icon setTintList(ColorStateList tintList) {
+        mTintList = tintList;
+        return this;
+    }
+
+    /**
+     * Store a blending mode to use whenever this Icon is drawn.
+     *
+     * @param mode a blending mode, as in {@link Drawable#setTintMode(PorterDuff.Mode)}, may be null
+     * @return this same object, for use in chained construction
+     */
+    public Icon setTintMode(PorterDuff.Mode mode) {
+        mTintMode = mode;
+        return this;
+    }
+
+    /**
      * Create an Icon pointing to an image file specified by path.
      *
      * @param path A path to a file that contains compressed bitmap data of
@@ -558,6 +624,15 @@
                 sb.append(" uri=").append(getUriString());
                 break;
         }
+        if (mTintList != null) {
+            sb.append(" tint=");
+            String sep = "";
+            for (int c : mTintList.getColors()) {
+                sb.append(String.format("%s0x%08x", sep, c));
+                sep = "|";
+            }
+        }
+        if (mTintMode != DEFAULT_TINT_MODE) sb.append(" mode=").append(mTintMode);
         sb.append(")");
         return sb.toString();
     }
@@ -603,31 +678,39 @@
                 throw new RuntimeException("invalid "
                         + this.getClass().getSimpleName() + " type in parcel: " + mType);
         }
+        if (in.readInt() == 1) {
+            mTintList = ColorStateList.CREATOR.createFromParcel(in);
+        }
+        mTintMode = PorterDuff.intToMode(in.readInt());
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mType);
         switch (mType) {
             case TYPE_BITMAP:
                 final Bitmap bits = getBitmap();
-                dest.writeInt(TYPE_BITMAP);
                 getBitmap().writeToParcel(dest, flags);
                 break;
             case TYPE_RESOURCE:
-                dest.writeInt(TYPE_RESOURCE);
                 dest.writeString(getResPackage());
                 dest.writeInt(getResId());
                 break;
             case TYPE_DATA:
-                dest.writeInt(TYPE_DATA);
                 dest.writeInt(getDataLength());
                 dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength());
                 break;
             case TYPE_URI:
-                dest.writeInt(TYPE_URI);
                 dest.writeString(getUriString());
                 break;
         }
+        if (mTintList == null) {
+            dest.writeInt(0);
+        } else {
+            dest.writeInt(1);
+            mTintList.writeToParcel(dest, flags);
+        }
+        dest.writeInt(PorterDuff.modeToInt(mTintMode));
     }
 
     public static final Parcelable.Creator<Icon> CREATOR
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 90891f6..8373c7f 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1248,16 +1248,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        final Drawable dr = getFirstNonNullDrawable();
-        if (dr != null) {
-            return dr.isDither();
-        } else {
-            return super.isDither();
-        }
-    }
-
-    @Override
     public void setAlpha(int alpha) {
         final ChildDrawable[] array = mLayerState.mChildren;
         final int N = mLayerState.mNum;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index adf53e3..152fe6a 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -374,11 +374,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mPaint == null ? DEFAULT_DITHER : mPaint.isDither();
-    }
-
-    @Override
     public void setAutoMirrored(boolean mirrored) {
         mNinePatchState.mAutoMirrored = mirrored;
     }
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index a669d3c..30b588e 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -328,11 +328,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mShapeState.mPaint.isDither();
-    }
-
-    @Override
     protected void onBoundsChange(Rect bounds) {
         super.onBoundsChange(bounds);
         updateShape();
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/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index a323065..6cf66cd 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -419,12 +419,12 @@
 bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
     mCanvas->clipRect(rect, op);
-    return mCanvas->isClipEmpty();
+    return !mCanvas->isClipEmpty();
 }
 
 bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
     mCanvas->clipPath(*path, op);
-    return mCanvas->isClipEmpty();
+    return !mCanvas->isClipEmpty();
 }
 
 bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
@@ -438,7 +438,7 @@
     } else {
         mCanvas->clipRect(SkRect::MakeEmpty(), op);
     }
-    return mCanvas->isClipEmpty();
+    return !mCanvas->isClipEmpty();
 }
 
 // ----------------------------------------------------------------------------
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/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 64333ad..003a274 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -272,7 +272,7 @@
     /**
      * Tunes to a given channel.
      *
-     * @param inputId The ID of TV input which will play the given channel.
+     * @param inputId The ID of the TV input for the given channel.
      * @param channelUri The URI of a channel.
      */
     public void tune(@NonNull String inputId, Uri channelUri) {
@@ -282,9 +282,9 @@
     /**
      * Tunes to a given channel.
      *
-     * @param inputId The ID of TV input which will play the given channel.
+     * @param inputId The ID of TV input for the given channel.
      * @param channelUri The URI of a channel.
-     * @param params Extra parameters which might be handled with the tune event.
+     * @param params Extra parameters.
      * @hide
      */
     @SystemApi
@@ -298,22 +298,26 @@
                 sMainTvView = new WeakReference<>(this);
             }
         }
-        if (mSessionCallback != null && mSessionCallback.mInputId.equals(inputId)) {
+        if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) {
             if (mSession != null) {
                 mSession.tune(channelUri, params);
             } else {
-                // Session is not created yet. Replace the channel which will be set once the
-                // session is made.
+                // createSession() was called but the actual session for the given inputId has not
+                // yet been created. Just replace the existing tuning params in the callback with
+                // the new ones and tune later in onSessionCreated(). It is not necessary to create
+                // a new callback because this tuning request was made on the same inputId.
                 mSessionCallback.mChannelUri = channelUri;
                 mSessionCallback.mTuneParams = params;
             }
         } else {
             resetInternal();
-            // When createSession() is called multiple times before the callback is called,
-            // only the callback of the last createSession() call will be actually called back.
-            // The previous callbacks will be ignored. For the logic, mSessionCallback
-            // is newly assigned for every createSession request and compared with
-            // MySessionCreateCallback.this.
+            // In case createSession() is called multiple times across different inputId's before
+            // any session is created (e.g. when quickly tuning to a channel from input A and then
+            // to another channel from input B), only the callback for the last createSession()
+            // should be invoked. (The previous callbacks are simply ignored.) To do that, we create
+            // a new callback each time and keep mSessionCallback pointing to the last one. If
+            // MySessionCallback.this is different from mSessionCallback, we know that this callback
+            // is obsolete and should ignore it.
             mSessionCallback = new MySessionCallback(inputId, channelUri, params);
             if (mTvInputManager != null) {
                 mTvInputManager.createSession(inputId, mSessionCallback, mHandler);
@@ -337,6 +341,7 @@
     }
 
     private void resetInternal() {
+        mSessionCallback = null;
         mPendingAppPrivateCommands.clear();
         if (mSession != null) {
             setSessionSurface(null);
@@ -344,7 +349,6 @@
             mUseRequestedSurfaceLayout = false;
             mSession.release();
             mSession = null;
-            mSessionCallback = null;
             resetSurfaceView();
         }
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index fe148da..c541bca 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -186,6 +186,9 @@
         }
 
         if (!mState.restored) {
+            // In this case, we set the activity title in AsyncTask.onPostExecute().  To prevent
+            // talkback from reading aloud the default title, we clear it here.
+            setTitle("");
             if (mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE) {
                 final Uri rootUri = getIntent().getData();
                 new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
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/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index b33b10b..25f8872 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -19,6 +19,7 @@
 import android.Manifest;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
@@ -114,6 +115,13 @@
     private static final int SERVICE_IBLUETOOTH = 1;
     private static final int SERVICE_IBLUETOOTHGATT = 2;
 
+    private static final String[] DEVICE_TYPE_NAMES = new String[] {
+            "???",
+            "BR/EDR",
+            "LE",
+            "DUAL"
+        };
+
     private final Context mContext;
     private static int mBleAppCount = 0;
 
@@ -1801,6 +1809,14 @@
         } else {
             ParcelFileDescriptor pfd = null;
             try {
+                writer.println("Bonded devices:");
+                for (BluetoothDevice device : mBluetooth.getBondedDevices()) {
+                    writer.println("  " + device.getAddress() +
+                            " [" + DEVICE_TYPE_NAMES[device.getType()] + "] " +
+                            device.getName());
+                }
+                writer.flush();
+
                 pfd = ParcelFileDescriptor.dup(fd);
                 mBluetooth.dump(pfd);
             } catch (RemoteException re) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 25d4d5e..2d5141e 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;
@@ -1559,7 +1560,7 @@
                 NetworkCapabilities.TRANSPORT_WIFI)) {
             timeout = Settings.Global.getInt(mContext.getContentResolver(),
                                              Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
-                                             5);
+                                             15);
             type = ConnectivityManager.TYPE_WIFI;
         } else {
             // do not track any other networks
@@ -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,21 +1993,28 @@
                 }
                 case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
                     final int netId = msg.arg2;
-                    if (msg.arg1 == 0) {
-                        setProvNotificationVisibleIntent(false, netId, null, 0, null, null);
+                    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, false);
                     } 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);
+                                nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(),
+                                (PendingIntent)msg.obj, nai.networkMisc.explicitlySelected);
                     }
                     break;
                 }
@@ -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;
         }
@@ -2440,7 +2447,7 @@
         PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
                 mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
         setProvNotificationVisibleIntent(true, nai.network.netId, NotificationType.NO_INTERNET,
-                nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(), pendingIntent);
+                nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(), pendingIntent, true);
     }
 
     private class InternalHandler extends Handler {
@@ -3233,7 +3240,7 @@
         // Concatenate the range of types onto the range of NetIDs.
         int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
         setProvNotificationVisibleIntent(visible, id, NotificationType.SIGN_IN,
-                networkType, null, pendingIntent);
+                networkType, null, pendingIntent, false);
     }
 
     /**
@@ -3252,11 +3259,12 @@
      *         we concatenate the range of types with the range of NetIDs.
      */
     private void setProvNotificationVisibleIntent(boolean visible, int id,
-            NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent) {
+            NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent,
+            boolean highPriority) {
         if (DBG) {
             log("setProvNotificationVisibleIntent " + notifyType + " visible=" + visible
                     + " networkType=" + getNetworkTypeName(networkType)
-                    + " extraInfo=" + extraInfo);
+                    + " extraInfo=" + extraInfo + " highPriority=" + highPriority);
         }
 
         Resources r = Resources.getSystem();
@@ -3311,6 +3319,12 @@
                     .setContentTitle(title)
                     .setContentText(details)
                     .setContentIntent(intent)
+                    .setLocalOnly(true)
+                    .setPriority(highPriority ?
+                            Notification.PRIORITY_HIGH :
+                            Notification.PRIORITY_DEFAULT)
+                    .setDefaults(Notification.DEFAULT_ALL)
+                    .setOnlyAlertOnce(true)
                     .build();
 
             try {
@@ -3571,12 +3585,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 +3671,7 @@
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities);
         enforceMeteredApnPolicy(networkCapabilities);
+        ensureImmutableCapabilities(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId());
@@ -4046,18 +4073,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 +4445,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 +4468,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 +4597,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/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 5436ce0..c5ea8bc 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -27,11 +27,10 @@
 import android.content.pm.UserInfo;
 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
 import static android.content.Context.USER_SERVICE;
-import static android.Manifest.permission.READ_PROFILE;
+import static android.Manifest.permission.READ_CONTACTS;
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.storage.IMountService;
 import android.os.ServiceManager;
@@ -264,12 +263,12 @@
     private final void checkReadPermission(String requestedKey, int userId) {
         final int callingUid = Binder.getCallingUid();
 
-        for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) {
-            String key = READ_PROFILE_PROTECTED_SETTINGS[i];
-            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE)
+        for (int i = 0; i < READ_CONTACTS_PROTECTED_SETTINGS.length; i++) {
+            String key = READ_CONTACTS_PROTECTED_SETTINGS[i];
+            if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_CONTACTS)
                     != PackageManager.PERMISSION_GRANTED) {
                 throw new SecurityException("uid=" + callingUid
-                        + " needs permission " + READ_PROFILE + " to read "
+                        + " needs permission " + READ_CONTACTS + " to read "
                         + requestedKey + " for user " + userId);
             }
         }
@@ -722,8 +721,8 @@
         Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
     };
 
-    // Reading these settings needs the profile permission
-    private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] {
+    // Reading these settings needs the contacts permission
+    private static final String[] READ_CONTACTS_PROTECTED_SETTINGS = new String[] {
         Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
         Secure.LOCK_SCREEN_OWNER_INFO
     };
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 458150c..7204aec 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1504,6 +1504,8 @@
         try {
             final NativeDaemonEvent res = mConnector.execute("volume", "benchmark", volId);
             return Long.parseLong(res.getMessage());
+        } catch (NativeDaemonTimeoutException e) {
+            return Long.MAX_VALUE;
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 78c7f38..e7979e4 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -421,7 +421,7 @@
             event = mResponseQueue.remove(sequenceNumber, timeout, logCmd);
             if (event == null) {
                 loge("timed-out waiting for response to " + logCmd);
-                throw new NativeDaemonFailureException(logCmd, event);
+                throw new NativeDaemonTimeoutException(logCmd, event);
             }
             if (VDBG) log("RMV <- {" + event + "}");
             events.add(event);
diff --git a/core/java/android/view/ViewAssistStructure.java b/services/core/java/com/android/server/NativeDaemonTimeoutException.java
similarity index 64%
copy from core/java/android/view/ViewAssistStructure.java
copy to services/core/java/com/android/server/NativeDaemonTimeoutException.java
index a66d93c..658f7d6 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/services/core/java/com/android/server/NativeDaemonTimeoutException.java
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
-package android.view;
+package com.android.server;
 
 /**
- * @deprecated Temporary until old apps can move off this.
+ * An exception that indicates there was a timeout with a
+ * {@link NativeDaemonConnector} operation.
  */
-@Deprecated
-public abstract class ViewAssistStructure extends ViewStructure {
+public class NativeDaemonTimeoutException extends NativeDaemonConnectorException {
+    public NativeDaemonTimeoutException(String command, NativeDaemonEvent event) {
+        super(command, event);
+    }
 }
+
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/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 3456dbc..50d311f 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1591,13 +1591,6 @@
             try {
                 final ContentValues values = new ContentValues();
                 values.put(ACCOUNTS_PASSWORD, password);
-                long time = 0;
-                // Only set current time, if it is a valid password. For clear password case, it
-                // should not be set.
-                if (password != null) {
-                    time = System.currentTimeMillis();
-                }
-                values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, time);
                 final long accountId = getAccountIdLocked(db, account);
                 if (accountId >= 0) {
                     final String[] argsAccountId = {String.valueOf(accountId)};
@@ -2130,7 +2123,7 @@
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
                     true /* stripAuthTokenFromResult */, null /* accountName */,
-                    false /* authDetailsRequired */) {
+                    false /* authDetailsRequired */, true /* updateLastAuthenticationTime */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
@@ -2207,7 +2200,7 @@
         try {
             new Session(accounts, response, accountType, expectActivityLaunch,
                     true /* stripAuthTokenFromResult */, null /* accountName */,
-                    false /* authDetailsRequired */) {
+                    false /* authDetailsRequired */, true /* updateLastAuthenticationTime */) {
                 @Override
                 public void run() throws RemoteException {
                     mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
@@ -2940,14 +2933,14 @@
             if (result != null) {
                 boolean isSuccessfulConfirmCreds = result.getBoolean(
                         AccountManager.KEY_BOOLEAN_RESULT, false);
-                boolean isSuccessfulUpdateCreds =
+                boolean isSuccessfulUpdateCredsOrAddAccount =
                         result.containsKey(AccountManager.KEY_ACCOUNT_NAME)
                         && result.containsKey(AccountManager.KEY_ACCOUNT_TYPE);
                 // We should only update lastAuthenticated time, if
                 // mUpdateLastAuthenticatedTime is true and the confirmRequest
                 // or updateRequest was successful
                 boolean needUpdate = mUpdateLastAuthenticatedTime
-                        && (isSuccessfulConfirmCreds || isSuccessfulUpdateCreds);
+                        && (isSuccessfulConfirmCreds || isSuccessfulUpdateCredsOrAddAccount);
                 if (needUpdate || mAuthDetailsRequired) {
                     boolean accountPresent = isAccountPresentForCaller(mAccountName, mAccountType);
                     if (needUpdate && accountPresent) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 3854e51..78557634 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -38,6 +38,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
@@ -629,7 +630,10 @@
         // Collect data now for the past activity.
         synchronized (mStats) {
             if (mStats.isOnBattery()) {
-                mHandler.scheduleWifiSync("wifi-data");
+                final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH ||
+                        powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
+                        : "inactive";
+                mHandler.scheduleWifiSync("wifi-data: " + type);
             }
             mStats.noteWifiRadioPowerState(powerState, tsNanos);
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 47d3bde..0dc4076 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3099,10 +3099,13 @@
                         || mContext.getResources().getBoolean(
                                 com.android.internal.R.bool.config_safe_media_volume_enabled);
 
+                boolean safeMediaVolumeBypass =
+                        SystemProperties.getBoolean("audio.safemedia.bypass", false);
+
                 // The persisted state is either "disabled" or "active": this is the state applied
                 // next time we boot and cannot be "inactive"
                 int persistedState;
-                if (safeMediaVolumeEnabled) {
+                if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
                     persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
                     // The state can already be "inactive" here if the user has forced it before
                     // the 30 seconds timeout for forced configuration. In this case we don't reset
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/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 62c686c..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";
@@ -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 41d3ffd..dbf0f17 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 {
@@ -309,6 +310,7 @@
     static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
     static final int SCAN_REQUIRE_KNOWN = 1<<12;
     static final int SCAN_MOVE = 1<<13;
+    static final int SCAN_INITIAL = 1<<14;
 
     static final int REMOVE_CHATTY = 1<<16;
 
@@ -509,7 +511,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 +1094,7 @@
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             }
         }
-        
+
         void doHandleMessage(Message msg) {
             switch (msg.what) {
                 case INIT_COPY: {
@@ -1839,7 +1841,7 @@
 
             // Set flag to monitor and not change apk file paths when
             // scanning install directories.
-            final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
+            final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
 
             final ArraySet<String> alreadyDexOpted = new ArraySet<String>();
 
@@ -2502,7 +2504,7 @@
         }
         return out;
     }
-    
+
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
         String[] out = new String[names.length];
@@ -2572,7 +2574,7 @@
         pi.protectionLevel = bp.protectionLevel;
         return pi;
     }
-    
+
     @Override
     public PermissionInfo getPermissionInfo(String name, int flags) {
         // reader
@@ -3052,7 +3054,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 +3356,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 +3386,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 +4216,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -4727,7 +4771,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -4778,7 +4822,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -6205,7 +6249,7 @@
                                 + "): packages=" + suid.packages);
                 }
             }
-            
+
             // Check if we are renaming from an original package name.
             PackageSetting origPackage = null;
             String realName = null;
@@ -6225,7 +6269,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 +6299,7 @@
                     }
                 }
             }
-            
+
             if (mTransferedPackages.contains(pkg.packageName)) {
                 Slog.w(TAG, "Package " + pkg.packageName
                         + " was transferred to another, but its .apk remains");
@@ -6280,24 +6324,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 +6457,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 +8377,7 @@
                 PackageParser.ActivityIntentInfo info) {
             return packageName.equals(info.activity.owner.packageName);
         }
-        
+
         @Override
         protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
                 int match, int userId) {
@@ -8556,7 +8600,7 @@
                 PackageParser.ServiceIntentInfo info) {
             return packageName.equals(info.service.owner.packageName);
         }
-        
+
         @Override
         protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
                 int match, int userId) {
@@ -9079,6 +9123,7 @@
             String installerPackageName, int installerUid, UserHandle user) {
         final VerificationParams verifParams = new VerificationParams(null, params.originatingUri,
                 params.referrerUri, installerUid, null);
+        verifParams.setInstallerUid(installerUid);
 
         final OriginInfo origin;
         if (stagedDir != null) {
@@ -11283,7 +11328,7 @@
 
     private boolean shouldCheckUpgradeKeySetLP(PackageSetting oldPs, int scanFlags) {
         // Can't rotate keys during boot or if sharedUser.
-        if (oldPs == null || (scanFlags&SCAN_BOOTING) != 0 || oldPs.sharedUser != null
+        if (oldPs == null || (scanFlags&SCAN_INITIAL) != 0 || oldPs.sharedUser != null
                 || !oldPs.keySetData.isUsingUpgradeKeySets()) {
             return false;
         }
@@ -11667,6 +11712,10 @@
                 || (args.volumeUuid != null));
         boolean replace = false;
         int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
+        if (args.move != null) {
+            // moving a complete application; perfom an initial scan on the new install location
+            scanFlags |= SCAN_INITIAL;
+        }
         // Result object to be returned
         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
 
@@ -14111,7 +14160,7 @@
         boolean checkin = false;
 
         String packageName = null;
-        
+
         int opti = 0;
         while (opti < args.length) {
             String opt = args[opti];
@@ -14963,7 +15012,7 @@
             for (PackageSetting ps : packages) {
                 final PackageParser.Package pkg;
                 try {
-                    pkg = scanPackageLI(ps.codePath, parseFlags, 0, 0, null);
+                    pkg = scanPackageLI(ps.codePath, parseFlags, SCAN_INITIAL, 0L, null);
                     loaded.add(pkg.applicationInfo);
                 } catch (PackageManagerException e) {
                     Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
@@ -15757,4 +15806,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/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 79dac14..93e1f18 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5381,10 +5381,16 @@
     }
 
     private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
-        if (!wakeInTheaterMode && isTheaterModeEnabled()) {
+        final boolean theaterModeEnabled = isTheaterModeEnabled();
+        if (!wakeInTheaterMode && theaterModeEnabled) {
             return false;
         }
 
+        if (theaterModeEnabled) {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.THEATER_MODE_ON, 0);
+        }
+
         mPowerManager.wakeUp(wakeTime);
         return true;
     }
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/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index f5c5861..51df31f 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -34,6 +34,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.Rect;
@@ -112,8 +113,6 @@
     private final Context mContext;
     private final TvInputHardwareManager mTvInputHardwareManager;
 
-    private final ContentResolver mContentResolver;
-
     // A global lock.
     private final Object mLock = new Object();
 
@@ -129,9 +128,8 @@
         super(context);
 
         mContext = context;
-        mContentResolver = context.getContentResolver();
-        mWatchLogHandler = new WatchLogHandler(mContentResolver, IoThread.get().getLooper());
-
+        mWatchLogHandler = new WatchLogHandler(mContext.getContentResolver(),
+                IoThread.get().getLooper());
         mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener());
 
         synchronized (mLock) {
@@ -246,7 +244,8 @@
 
                 ContentProviderResult[] results = null;
                 try {
-                    results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+                    ContentResolver cr = getContentResolverForUser(getChangingUserId());
+                    results = cr.applyBatch(TvContract.AUTHORITY, operations);
                 } catch (RemoteException | OperationApplicationException e) {
                     Slog.e(TAG, "error in applyBatch", e);
                 }
@@ -400,17 +399,18 @@
             if (mCurrentUserId == userId) {
                 return;
             }
-            // final int oldUserId = mCurrentUserId;
-            // TODO: Release services and sessions in the old user state, if needed.
-            mCurrentUserId = userId;
+            clearSessionAndServiceStatesLocked(mUserStates.get(mCurrentUserId));
 
+            mCurrentUserId = userId;
             UserState userState = mUserStates.get(userId);
             if (userState == null) {
                 userState = new UserState(mContext, userId);
+                mUserStates.put(userId, userState);
             }
-            mUserStates.put(userId, userState);
             buildTvInputListLocked(userId, null);
             buildTvContentRatingSystemListLocked(userId);
+            mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_SWITCH_CONTENT_RESOLVER,
+                    getContentResolverForUser(userId)).sendToTarget();
         }
     }
 
@@ -420,30 +420,7 @@
             if (userState == null) {
                 return;
             }
-            // Release created sessions.
-            for (SessionState state : userState.sessionStateMap.values()) {
-                if (state.session != null) {
-                    try {
-                        state.session.release();
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in release", e);
-                    }
-                }
-            }
-            userState.sessionStateMap.clear();
-
-            // Unregister all callbacks and unbind all services.
-            for (ServiceState serviceState : userState.serviceStateMap.values()) {
-                if (serviceState.callback != null) {
-                    try {
-                        serviceState.service.unregisterCallback(serviceState.callback);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "error in unregisterCallback", e);
-                    }
-                }
-                mContext.unbindService(serviceState.connection);
-            }
-            userState.serviceStateMap.clear();
+            clearSessionAndServiceStatesLocked(userState);
 
             // Clear everything else.
             userState.inputMap.clear();
@@ -457,6 +434,45 @@
         }
     }
 
+    private void clearSessionAndServiceStatesLocked(UserState userState) {
+        // Release created sessions.
+        for (SessionState state : userState.sessionStateMap.values()) {
+            if (state.session != null) {
+                try {
+                    state.session.release();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in release", e);
+                }
+            }
+        }
+        userState.sessionStateMap.clear();
+
+        // Unregister all callbacks and unbind all services.
+        for (ServiceState serviceState : userState.serviceStateMap.values()) {
+            if (serviceState.callback != null) {
+                try {
+                    serviceState.service.unregisterCallback(serviceState.callback);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "error in unregisterCallback", e);
+                }
+            }
+            mContext.unbindService(serviceState.connection);
+        }
+        userState.serviceStateMap.clear();
+    }
+
+    private ContentResolver getContentResolverForUser(int userId) {
+        UserHandle user = new UserHandle(userId);
+        Context context;
+        try {
+            context = mContext.createPackageContextAsUser("android", 0, user);
+        } catch (NameNotFoundException e) {
+            Slog.e(TAG, "failed to create package contenxt as user " + user);
+            context = mContext;
+        }
+        return context.getContentResolver();
+    }
+
     private UserState getUserStateLocked(int userId) {
         UserState userState = mUserStates.get(userId);
         if (userState == null) {
@@ -2384,12 +2400,13 @@
         // Here the system supplies the database the smallest set of information only that is
         // sufficient to consolidate the log entries while minimizing database operations in the
         // system service.
-        private static final int MSG_LOG_WATCH_START = 1;
-        private static final int MSG_LOG_WATCH_END = 2;
+        static final int MSG_LOG_WATCH_START = 1;
+        static final int MSG_LOG_WATCH_END = 2;
+        static final int MSG_SWITCH_CONTENT_RESOLVER = 3;
 
-        private final ContentResolver mContentResolver;
+        private ContentResolver mContentResolver;
 
-        public WatchLogHandler(ContentResolver contentResolver, Looper looper) {
+        WatchLogHandler(ContentResolver contentResolver, Looper looper) {
             super(looper);
             mContentResolver = contentResolver;
         }
@@ -2419,7 +2436,7 @@
 
                     mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values);
                     args.recycle();
-                    return;
+                    break;
                 }
                 case MSG_LOG_WATCH_END: {
                     SomeArgs args = (SomeArgs) msg.obj;
@@ -2434,11 +2451,15 @@
 
                     mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values);
                     args.recycle();
-                    return;
+                    break;
+                }
+                case MSG_SWITCH_CONTENT_RESOLVER: {
+                    mContentResolver = (ContentResolver) msg.obj;
+                    break;
                 }
                 default: {
-                    Slog.w(TAG, "Unhandled message code: " + msg.what);
-                    return;
+                    Slog.w(TAG, "unhandled message code: " + msg.what);
+                    break;
                 }
             }
         }
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 74adc6b..e44a7ab87 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4217,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);
             }
@@ -4388,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);
             }
@@ -6390,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();
+            }
+        }
+    }
 }