Merge "Deliver start service args with ParcelledListSlice." into oc-dev
diff --git a/Android.mk b/Android.mk
index 634272b..ee7d471 100644
--- a/Android.mk
+++ b/Android.mk
@@ -367,7 +367,6 @@
 	core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
 	core/java/com/android/internal/backup/IBackupTransport.aidl \
 	core/java/com/android/internal/backup/IObbBackupService.aidl \
-	core/java/com/android/internal/font/IFontManager.aidl \
 	core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \
 	core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
 	core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl \
@@ -1461,8 +1460,7 @@
 LOCAL_SRC_FILES := \
     $(call all-proto-files-under, core/proto) \
     $(call all-proto-files-under, libs/incident/proto)
-LOCAL_SHARED_LIBRARIES := libprotobuf-cpp-full
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
 
 # ====  c++ proto host library  ==============================
 include $(CLEAR_VARS)
diff --git a/api/current.txt b/api/current.txt
index af3ef9e..c5f4816 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3578,7 +3578,7 @@
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public void enterPictureInPictureMode();
     method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public void finish();
     method public void finishActivity(int);
     method public void finishActivityFromChild(android.app.Activity, int);
@@ -4358,7 +4358,7 @@
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public android.app.ActionBar getActionBar();
     method public final android.content.Context getContext();
     method public android.view.View getCurrentFocus();
@@ -7044,6 +7044,7 @@
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
     method public boolean isRequestPinAppWidgetSupported();
@@ -8889,7 +8890,6 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
-    field public static final java.lang.String FONT_SERVICE = "font";
     field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
@@ -10645,6 +10645,7 @@
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
     field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+    field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
     field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
     field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
     field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -13242,7 +13243,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public boolean setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -13776,8 +13777,8 @@
     method public static android.graphics.Typeface.Builder obtain();
     method public void recycle();
     method public void reset();
-    method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String);
-    method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]);
+    method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
     method public android.graphics.Typeface.Builder setItalic(int);
     method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
     method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
@@ -14387,6 +14388,21 @@
     field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
   }
 
+  public final class FontVariationAxis implements android.os.Parcelable {
+    ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public int describeContents();
+    method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public float getStyleValue();
+    method public java.lang.String getTag();
+    method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
+  }
+
+  public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
+    ctor public FontVariationAxis.InvalidFormatException(java.lang.String);
+  }
+
 }
 
 package android.graphics.pdf {
@@ -15982,11 +15998,11 @@
     ctor public UsbRequest();
     method public boolean cancel();
     method public void close();
-    method public boolean enqueue(java.nio.ByteBuffer);
     method public java.lang.Object getClientData();
     method public android.hardware.usb.UsbEndpoint getEndpoint();
     method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
     method public deprecated boolean queue(java.nio.ByteBuffer, int);
+    method public boolean queue(java.nio.ByteBuffer);
     method public void setClientData(java.lang.Object);
   }
 
@@ -22999,6 +23015,7 @@
     method public void setProfile(android.media.CamcorderProfile);
     method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
     method public void setVideoEncodingBitRate(int);
+    method public void setVideoEncodingProfileLevel(int, int);
     method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
     method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
     method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -24540,85 +24557,6 @@
     field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
   }
 
-  public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
-    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-    field public static final java.lang.String COLUMN_AUTHOR = "author";
-    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
-    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
-    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
-    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
-    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
-    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
-    field public static final java.lang.String COLUMN_LIVE = "live";
-    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
-    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
-    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
-    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
-    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
-    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
-    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
-    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
-    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
-    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
-    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
-    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
-    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
-    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
-    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-  }
-
-  public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
-    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
-    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
-    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
-    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
-    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
-    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
-    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
-    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
-    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
-    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
-    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
-    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
-    field public static final java.lang.String COLUMN_TITLE = "title";
-    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
-    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
-    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
-  }
-
   public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
     field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
   }
@@ -24705,22 +24643,116 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "logo";
   }
 
-  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+    field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+    field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String COLUMN_WEIGHT = "weight";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+    field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+    field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+    field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+    field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+    field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+    field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+    field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+    field public static final int TYPE_ALBUM = 8; // 0x8
+    field public static final int TYPE_ARTIST = 9; // 0x9
+    field public static final int TYPE_CHANNEL = 6; // 0x6
+    field public static final int TYPE_CLIP = 4; // 0x4
+    field public static final int TYPE_EVENT = 5; // 0x5
+    field public static final int TYPE_MOVIE = 0; // 0x0
+    field public static final int TYPE_PLAYLIST = 10; // 0xa
+    field public static final int TYPE_STATION = 11; // 0xb
+    field public static final int TYPE_TRACK = 7; // 0x7
+    field public static final int TYPE_TV_EPISODE = 3; // 0x3
+    field public static final int TYPE_TV_SEASON = 2; // 0x2
+    field public static final int TYPE_TV_SERIES = 1; // 0x1
   }
 
-  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
     field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
     field public static final android.net.Uri CONTENT_URI;
@@ -24749,32 +24781,126 @@
     field public static final java.lang.String TRAVEL = "TRAVEL";
   }
 
-  public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
+  public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
     field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
     field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
     field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
     field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
     field public static final android.net.Uri CONTENT_URI;
   }
 
-  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
     ctor public TvContract.WatchNextPrograms();
+    field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+    field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+    field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
     field public static final java.lang.String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
-    field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+    field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+    field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+    field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+    field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+    field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+    field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+    field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+    field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+    field public static final int TYPE_ALBUM = 8; // 0x8
+    field public static final int TYPE_ARTIST = 9; // 0x9
+    field public static final int TYPE_CHANNEL = 6; // 0x6
+    field public static final int TYPE_CLIP = 4; // 0x4
+    field public static final int TYPE_EVENT = 5; // 0x5
+    field public static final int TYPE_MOVIE = 0; // 0x0
+    field public static final int TYPE_PLAYLIST = 10; // 0xa
+    field public static final int TYPE_STATION = 11; // 0xb
+    field public static final int TYPE_TRACK = 7; // 0x7
+    field public static final int TYPE_TV_EPISODE = 3; // 0x3
+    field public static final int TYPE_TV_SEASON = 2; // 0x2
+    field public static final int TYPE_TV_SERIES = 1; // 0x1
+    field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
+    field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
+    field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
+    field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
   }
 
   public final class TvInputInfo implements android.os.Parcelable {
@@ -34395,14 +34521,15 @@
 
   public static final class FontsContract.Columns implements android.provider.BaseColumns {
     ctor public FontsContract.Columns();
+    field public static final java.lang.String ITALIC = "font_italic";
     field public static final java.lang.String RESULT_CODE = "result_code";
     field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
     field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
     field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
     field public static final int RESULT_CODE_OK = 0; // 0x0
-    field public static final java.lang.String STYLE = "font_style";
     field public static final java.lang.String TTC_INDEX = "font_ttc_index";
     field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+    field public static final java.lang.String WEIGHT = "font_weight";
   }
 
   public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -38624,6 +38751,7 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public final long getConnectTimeMillis();
+    method public long getCreationTimeMillis();
     method public android.telecom.DisconnectCause getDisconnectCause();
     method public android.os.Bundle getExtras();
     method public android.telecom.GatewayInfo getGatewayInfo();
@@ -41050,65 +41178,6 @@
     method public android.text.Editable newEditable(java.lang.CharSequence);
   }
 
-  public final class FontConfig implements android.os.Parcelable {
-    ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]);
-    method public int describeContents();
-    method public android.text.FontConfig.Alias[] getAliases();
-    method public android.text.FontConfig.Family[] getFamilies();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
-  }
-
-  public static final class FontConfig.Alias implements android.os.Parcelable {
-    ctor public FontConfig.Alias(java.lang.String, java.lang.String, int);
-    method public int describeContents();
-    method public java.lang.String getName();
-    method public java.lang.String getToName();
-    method public int getWeight();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
-  }
-
-  public static final class FontConfig.Axis implements android.os.Parcelable {
-    ctor public FontConfig.Axis(int, float);
-    ctor public FontConfig.Axis(java.lang.String, float);
-    method public int describeContents();
-    method public float getStyleValue();
-    method public int getTag();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR;
-  }
-
-  public static final class FontConfig.Family implements android.os.Parcelable {
-    ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int);
-    method public int describeContents();
-    method public android.text.FontConfig.Font[] getFonts();
-    method public java.lang.String getLanguage();
-    method public java.lang.String getName();
-    method public int getVariant();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR;
-    field public static final int VARIANT_COMPACT = 1; // 0x1
-    field public static final int VARIANT_DEFAULT = 0; // 0x0
-    field public static final int VARIANT_ELEGANT = 2; // 0x2
-  }
-
-  public static final class FontConfig.Font implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.text.FontConfig.Axis[] getAxes();
-    method public java.lang.String getFontName();
-    method public int getTtcIndex();
-    method public android.net.Uri getUri();
-    method public int getWeight();
-    method public boolean isItalic();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
-  }
-
-  public final class FontManager {
-    method public android.text.FontConfig getSystemFonts();
-  }
-
   public abstract interface GetChars implements java.lang.CharSequence {
     method public abstract void getChars(int, int, char[], int);
   }
@@ -41256,6 +41325,8 @@
     field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
     field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
     field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
   }
 
   public static final class Layout.Alignment extends java.lang.Enum {
@@ -41457,7 +41528,7 @@
     method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
     method public android.text.StaticLayout.Builder setIncludePad(boolean);
     method public android.text.StaticLayout.Builder setIndents(int[], int[]);
-    method public android.text.StaticLayout.Builder setJustify(boolean);
+    method public android.text.StaticLayout.Builder setJustificationMode(int);
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46536,7 +46607,7 @@
     method public void clearFlags(int);
     method public abstract void closeAllPanels();
     method public abstract void closePanel(int);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public boolean getAllowEnterTransitionOverlap();
     method public boolean getAllowReturnTransitionOverlap();
     method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -48661,7 +48732,7 @@
     method public abstract boolean getOffscreenPreRaster();
     method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
     method public abstract java.lang.String getSansSerifFontFamily();
-    method public abstract boolean getSaveFormData();
+    method public abstract deprecated boolean getSaveFormData();
     method public abstract deprecated boolean getSavePassword();
     method public abstract java.lang.String getSerifFontFamily();
     method public abstract java.lang.String getStandardFontFamily();
@@ -48710,7 +48781,7 @@
     method public abstract deprecated void setPluginState(android.webkit.WebSettings.PluginState);
     method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
     method public abstract void setSansSerifFontFamily(java.lang.String);
-    method public abstract void setSaveFormData(boolean);
+    method public abstract deprecated void setSaveFormData(boolean);
     method public abstract deprecated void setSavePassword(boolean);
     method public abstract void setSerifFontFamily(java.lang.String);
     method public abstract void setStandardFontFamily(java.lang.String);
@@ -49001,12 +49072,12 @@
 
   public abstract class WebViewDatabase {
     ctor public WebViewDatabase();
-    method public abstract void clearFormData();
+    method public abstract deprecated void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
     method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
-    method public abstract boolean hasFormData();
+    method public abstract deprecated boolean hasFormData();
     method public abstract boolean hasHttpAuthUsernamePassword();
     method public abstract deprecated boolean hasUsernamePassword();
     method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -51267,7 +51338,7 @@
     method public boolean getIncludeFontPadding();
     method public android.os.Bundle getInputExtras(boolean);
     method public int getInputType();
-    method public boolean getJustify();
+    method public int getJustificationMode();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
@@ -51362,7 +51433,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public boolean setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
@@ -51380,7 +51451,7 @@
     method public void setIncludeFontPadding(boolean);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
-    method public void setJustify(boolean);
+    method public void setJustificationMode(int);
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
diff --git a/api/removed.txt b/api/removed.txt
index 42b2ae6..d20c08c 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -296,6 +296,10 @@
     field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
   }
 
+  public static final class FontsContract.Columns implements android.provider.BaseColumns {
+    field public static final java.lang.String STYLE = "font_style";
+  }
+
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 73cf776..9b295bf 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3702,7 +3702,7 @@
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public void enterPictureInPictureMode();
     method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public void finish();
     method public void finishActivity(int);
     method public void finishActivityFromChild(android.app.Activity, int);
@@ -4509,7 +4509,7 @@
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public android.app.ActionBar getActionBar();
     method public final android.content.Context getContext();
     method public android.view.View getCurrentFocus();
@@ -4621,6 +4621,7 @@
     method public android.database.Cursor query(android.app.DownloadManager.Query);
     method public int remove(long...);
     field public static final java.lang.String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
+    field public static final java.lang.String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
     field public static final java.lang.String ACTION_NOTIFICATION_CLICKED = "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
     field public static final java.lang.String ACTION_VIEW_DOWNLOADS = "android.intent.action.VIEW_DOWNLOADS";
     field public static final java.lang.String COLUMN_BYTES_DOWNLOADED_SO_FAR = "bytes_so_far";
@@ -7502,6 +7503,7 @@
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
     method public boolean isRequestPinAppWidgetSupported();
@@ -9386,7 +9388,6 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
-    field public static final java.lang.String FONT_SERVICE = "font";
     field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
@@ -9797,6 +9798,7 @@
     field public static final java.lang.String ACTION_DREAMING_STARTED = "android.intent.action.DREAMING_STARTED";
     field public static final java.lang.String ACTION_DREAMING_STOPPED = "android.intent.action.DREAMING_STOPPED";
     field public static final java.lang.String ACTION_EDIT = "android.intent.action.EDIT";
+    field public static final deprecated java.lang.String ACTION_EPHEMERAL_RESOLVER_SETTINGS = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
     field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_AVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE";
     field public static final java.lang.String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
     field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
@@ -9809,7 +9811,10 @@
     field public static final java.lang.String ACTION_INPUT_METHOD_CHANGED = "android.intent.action.INPUT_METHOD_CHANGED";
     field public static final java.lang.String ACTION_INSERT = "android.intent.action.INSERT";
     field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
+    field public static final deprecated java.lang.String ACTION_INSTALL_EPHEMERAL_PACKAGE = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+    field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
     field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
+    field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
     field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
     field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
     field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
@@ -9868,6 +9873,8 @@
     field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
     field public static final java.lang.String ACTION_QUICK_VIEW = "android.intent.action.QUICK_VIEW";
     field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
+    field public static final deprecated java.lang.String ACTION_RESOLVE_EPHEMERAL_PACKAGE = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+    field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
     field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
     field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
     field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
@@ -9877,6 +9884,7 @@
     field public static final java.lang.String ACTION_SEND = "android.intent.action.SEND";
     field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
     field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
+    field public static final deprecated java.lang.String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
     field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
     field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
     field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
@@ -9951,6 +9959,8 @@
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
     field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
+    field public static final deprecated java.lang.String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
+    field public static final deprecated java.lang.String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
     field public static final deprecated java.lang.String EXTRA_CHANGED_COMPONENT_NAME = "android.intent.extra.changed_component_name";
     field public static final java.lang.String EXTRA_CHANGED_COMPONENT_NAME_LIST = "android.intent.extra.changed_component_name_list";
     field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
@@ -9960,7 +9970,14 @@
     field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
     field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
     field public static final java.lang.String EXTRA_CONTENT_ANNOTATIONS = "android.intent.extra.CONTENT_ANNOTATIONS";
+    field public static final deprecated java.lang.String EXTRA_CSS_INDICATOR = "cssIndicator";
+    field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long";
+    field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_ALPHA_SHORT = "data-operator-alpha-short";
+    field public static final deprecated java.lang.String EXTRA_DATA_OPERATOR_NUMERIC = "data-operator-numeric";
+    field public static final deprecated java.lang.String EXTRA_DATA_RADIO_TECH = "dataRadioTechnology";
+    field public static final deprecated java.lang.String EXTRA_DATA_REG_STATE = "dataRegState";
     field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
+    field public static final deprecated java.lang.String EXTRA_DATA_ROAMING_TYPE = "dataRoamingType";
     field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
     field public static final int EXTRA_DOCK_STATE_CAR = 2; // 0x2
     field public static final int EXTRA_DOCK_STATE_DESK = 1; // 0x1
@@ -9969,6 +9986,7 @@
     field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
     field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
     field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+    field public static final deprecated java.lang.String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
     field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
     field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
     field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
@@ -9976,10 +9994,18 @@
     field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
     field public static final java.lang.String EXTRA_INSTALLER_PACKAGE_NAME = "android.intent.extra.INSTALLER_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_INTENT = "android.intent.extra.INTENT";
+    field public static final deprecated java.lang.String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION = "isDataRoamingFromRegistration";
+    field public static final deprecated java.lang.String EXTRA_IS_USING_CARRIER_AGGREGATION = "isUsingCarrierAggregation";
     field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
     field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
+    field public static final deprecated java.lang.String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
+    field public static final deprecated java.lang.String EXTRA_MANUAL = "manual";
     field public static final java.lang.String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
+    field public static final deprecated java.lang.String EXTRA_NETWORK_ID = "networkId";
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
+    field public static final deprecated java.lang.String EXTRA_OPERATOR_ALPHA_LONG = "operator-alpha-long";
+    field public static final deprecated java.lang.String EXTRA_OPERATOR_ALPHA_SHORT = "operator-alpha-short";
+    field public static final deprecated java.lang.String EXTRA_OPERATOR_NUMERIC = "operator-numeric";
     field public static final java.lang.String EXTRA_ORIGINATING_UID = "android.intent.extra.ORIGINATING_UID";
     field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PACKAGES = "android.intent.extra.PACKAGES";
@@ -10011,11 +10037,15 @@
     field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
     field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
     field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
+    field public static final deprecated java.lang.String EXTRA_SYSTEM_ID = "systemId";
     field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
     field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
     field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
     field public static final java.lang.String EXTRA_USER = "android.intent.extra.USER";
+    field public static final deprecated java.lang.String EXTRA_VOICE_RADIO_TECH = "radioTechnology";
+    field public static final deprecated java.lang.String EXTRA_VOICE_REG_STATE = "voiceRegState";
+    field public static final deprecated java.lang.String EXTRA_VOICE_ROAMING_TYPE = "voiceRoamingType";
     field public static final int FILL_IN_ACTION = 1; // 0x1
     field public static final int FILL_IN_CATEGORIES = 4; // 0x4
     field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -11298,6 +11328,7 @@
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
     field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+    field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
     field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
     field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
     field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -13974,7 +14005,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public boolean setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -14508,8 +14539,8 @@
     method public static android.graphics.Typeface.Builder obtain();
     method public void recycle();
     method public void reset();
-    method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String);
-    method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]);
+    method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
     method public android.graphics.Typeface.Builder setItalic(int);
     method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
     method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
@@ -15119,6 +15150,21 @@
     field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
   }
 
+  public final class FontVariationAxis implements android.os.Parcelable {
+    ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public int describeContents();
+    method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public float getStyleValue();
+    method public java.lang.String getTag();
+    method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
+  }
+
+  public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
+    ctor public FontVariationAxis.InvalidFormatException(java.lang.String);
+  }
+
 }
 
 package android.graphics.pdf {
@@ -17442,11 +17488,11 @@
     ctor public UsbRequest();
     method public boolean cancel();
     method public void close();
-    method public boolean enqueue(java.nio.ByteBuffer);
     method public java.lang.Object getClientData();
     method public android.hardware.usb.UsbEndpoint getEndpoint();
     method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
     method public deprecated boolean queue(java.nio.ByteBuffer, int);
+    method public boolean queue(java.nio.ByteBuffer);
     method public void setClientData(java.lang.Object);
   }
 
@@ -22841,6 +22887,7 @@
     method public void adjustStreamVolume(int, int, int);
     method public void adjustSuggestedStreamVolume(int, int, int);
     method public void adjustVolume(int, int);
+    method public int dispatchAudioFocusChange(android.media.AudioFocusInfo, int, android.media.audiopolicy.AudioPolicy);
     method public void dispatchMediaKeyEvent(android.view.KeyEvent);
     method public int generateAudioSessionId();
     method public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
@@ -24792,6 +24839,7 @@
     method public void setProfile(android.media.CamcorderProfile);
     method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
     method public void setVideoEncodingBitRate(int);
+    method public void setVideoEncodingProfileLevel(int, int);
     method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
     method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
     method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -25842,8 +25890,10 @@
 
   public static abstract class AudioPolicy.AudioPolicyFocusListener {
     ctor public AudioPolicy.AudioPolicyFocusListener();
+    method public void onAudioFocusAbandon(android.media.AudioFocusInfo);
     method public void onAudioFocusGrant(android.media.AudioFocusInfo, int);
     method public void onAudioFocusLoss(android.media.AudioFocusInfo, boolean);
+    method public void onAudioFocusRequest(android.media.AudioFocusInfo, int);
   }
 
   public static abstract class AudioPolicy.AudioPolicyStatusListener {
@@ -25858,6 +25908,7 @@
     method public android.media.audiopolicy.AudioPolicy build();
     method public void setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener);
     method public void setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener);
+    method public android.media.audiopolicy.AudioPolicy.Builder setIsAudioFocusPolicy(boolean);
     method public android.media.audiopolicy.AudioPolicy.Builder setLooper(android.os.Looper) throws java.lang.IllegalArgumentException;
   }
 
@@ -26481,85 +26532,6 @@
     field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
   }
 
-  public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
-    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-    field public static final java.lang.String COLUMN_AUTHOR = "author";
-    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
-    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
-    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
-    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
-    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
-    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
-    field public static final java.lang.String COLUMN_LIVE = "live";
-    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
-    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
-    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
-    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
-    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
-    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
-    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
-    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
-    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
-    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
-    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
-    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
-    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
-    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
-    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-  }
-
-  public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
-    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
-    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
-    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
-    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
-    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
-    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
-    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
-    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
-    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
-    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
-    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
-    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
-    field public static final java.lang.String COLUMN_TITLE = "title";
-    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
-    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
-    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
-  }
-
   public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
     field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
   }
@@ -26647,22 +26619,116 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "logo";
   }
 
-  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+    field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+    field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String COLUMN_WEIGHT = "weight";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+    field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+    field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+    field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+    field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+    field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+    field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+    field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+    field public static final int TYPE_ALBUM = 8; // 0x8
+    field public static final int TYPE_ARTIST = 9; // 0x9
+    field public static final int TYPE_CHANNEL = 6; // 0x6
+    field public static final int TYPE_CLIP = 4; // 0x4
+    field public static final int TYPE_EVENT = 5; // 0x5
+    field public static final int TYPE_MOVIE = 0; // 0x0
+    field public static final int TYPE_PLAYLIST = 10; // 0xa
+    field public static final int TYPE_STATION = 11; // 0xb
+    field public static final int TYPE_TRACK = 7; // 0x7
+    field public static final int TYPE_TV_EPISODE = 3; // 0x3
+    field public static final int TYPE_TV_SEASON = 2; // 0x2
+    field public static final int TYPE_TV_SERIES = 1; // 0x1
   }
 
-  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
     field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
     field public static final android.net.Uri CONTENT_URI;
@@ -26691,32 +26757,126 @@
     field public static final java.lang.String TRAVEL = "TRAVEL";
   }
 
-  public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
+  public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
     field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
     field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
     field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
     field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
     field public static final android.net.Uri CONTENT_URI;
   }
 
-  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
     ctor public TvContract.WatchNextPrograms();
+    field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+    field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+    field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
     field public static final java.lang.String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
-    field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+    field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+    field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+    field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+    field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+    field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+    field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+    field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+    field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+    field public static final int TYPE_ALBUM = 8; // 0x8
+    field public static final int TYPE_ARTIST = 9; // 0x9
+    field public static final int TYPE_CHANNEL = 6; // 0x6
+    field public static final int TYPE_CLIP = 4; // 0x4
+    field public static final int TYPE_EVENT = 5; // 0x5
+    field public static final int TYPE_MOVIE = 0; // 0x0
+    field public static final int TYPE_PLAYLIST = 10; // 0xa
+    field public static final int TYPE_STATION = 11; // 0xb
+    field public static final int TYPE_TRACK = 7; // 0x7
+    field public static final int TYPE_TV_EPISODE = 3; // 0x3
+    field public static final int TYPE_TV_SEASON = 2; // 0x2
+    field public static final int TYPE_TV_SERIES = 1; // 0x1
+    field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
+    field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
+    field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
+    field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
   }
 
   public static final class TvContract.WatchedPrograms implements android.media.tv.TvContract.BaseTvColumns {
@@ -37300,14 +37460,15 @@
 
   public static final class FontsContract.Columns implements android.provider.BaseColumns {
     ctor public FontsContract.Columns();
+    field public static final java.lang.String ITALIC = "font_italic";
     field public static final java.lang.String RESULT_CODE = "result_code";
     field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
     field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
     field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
     field public static final int RESULT_CODE_OK = 0; // 0x0
-    field public static final java.lang.String STYLE = "font_style";
     field public static final java.lang.String TTC_INDEX = "font_ttc_index";
     field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+    field public static final java.lang.String WEIGHT = "font_weight";
   }
 
   public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -41782,6 +41943,7 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public final long getConnectTimeMillis();
+    method public long getCreationTimeMillis();
     method public android.telecom.DisconnectCause getDisconnectCause();
     method public android.os.Bundle getExtras();
     method public android.telecom.GatewayInfo getGatewayInfo();
@@ -44508,65 +44670,6 @@
     method public android.text.Editable newEditable(java.lang.CharSequence);
   }
 
-  public final class FontConfig implements android.os.Parcelable {
-    ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]);
-    method public int describeContents();
-    method public android.text.FontConfig.Alias[] getAliases();
-    method public android.text.FontConfig.Family[] getFamilies();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
-  }
-
-  public static final class FontConfig.Alias implements android.os.Parcelable {
-    ctor public FontConfig.Alias(java.lang.String, java.lang.String, int);
-    method public int describeContents();
-    method public java.lang.String getName();
-    method public java.lang.String getToName();
-    method public int getWeight();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
-  }
-
-  public static final class FontConfig.Axis implements android.os.Parcelable {
-    ctor public FontConfig.Axis(int, float);
-    ctor public FontConfig.Axis(java.lang.String, float);
-    method public int describeContents();
-    method public float getStyleValue();
-    method public int getTag();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR;
-  }
-
-  public static final class FontConfig.Family implements android.os.Parcelable {
-    ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int);
-    method public int describeContents();
-    method public android.text.FontConfig.Font[] getFonts();
-    method public java.lang.String getLanguage();
-    method public java.lang.String getName();
-    method public int getVariant();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR;
-    field public static final int VARIANT_COMPACT = 1; // 0x1
-    field public static final int VARIANT_DEFAULT = 0; // 0x0
-    field public static final int VARIANT_ELEGANT = 2; // 0x2
-  }
-
-  public static final class FontConfig.Font implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.text.FontConfig.Axis[] getAxes();
-    method public java.lang.String getFontName();
-    method public int getTtcIndex();
-    method public android.net.Uri getUri();
-    method public int getWeight();
-    method public boolean isItalic();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
-  }
-
-  public final class FontManager {
-    method public android.text.FontConfig getSystemFonts();
-  }
-
   public abstract interface GetChars implements java.lang.CharSequence {
     method public abstract void getChars(int, int, char[], int);
   }
@@ -44714,6 +44817,8 @@
     field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
     field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
     field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
   }
 
   public static final class Layout.Alignment extends java.lang.Enum {
@@ -44915,7 +45020,7 @@
     method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
     method public android.text.StaticLayout.Builder setIncludePad(boolean);
     method public android.text.StaticLayout.Builder setIndents(int[], int[]);
-    method public android.text.StaticLayout.Builder setJustify(boolean);
+    method public android.text.StaticLayout.Builder setJustificationMode(int);
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -49995,7 +50100,7 @@
     method public void clearFlags(int);
     method public abstract void closeAllPanels();
     method public abstract void closePanel(int);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public boolean getAllowEnterTransitionOverlap();
     method public boolean getAllowReturnTransitionOverlap();
     method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -52205,7 +52310,7 @@
     method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
     method public abstract deprecated boolean getPluginsEnabled();
     method public abstract java.lang.String getSansSerifFontFamily();
-    method public abstract boolean getSaveFormData();
+    method public abstract deprecated boolean getSaveFormData();
     method public abstract deprecated boolean getSavePassword();
     method public abstract java.lang.String getSerifFontFamily();
     method public abstract java.lang.String getStandardFontFamily();
@@ -52260,7 +52365,7 @@
     method public abstract deprecated void setPluginsEnabled(boolean);
     method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
     method public abstract void setSansSerifFontFamily(java.lang.String);
-    method public abstract void setSaveFormData(boolean);
+    method public abstract deprecated void setSaveFormData(boolean);
     method public abstract deprecated void setSavePassword(boolean);
     method public abstract void setSerifFontFamily(java.lang.String);
     method public abstract void setStandardFontFamily(java.lang.String);
@@ -52588,12 +52693,12 @@
 
   public abstract class WebViewDatabase {
     ctor public WebViewDatabase();
-    method public abstract void clearFormData();
+    method public abstract deprecated void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
     method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
-    method public abstract boolean hasFormData();
+    method public abstract deprecated boolean hasFormData();
     method public abstract boolean hasHttpAuthUsernamePassword();
     method public abstract deprecated boolean hasUsernamePassword();
     method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -55093,7 +55198,7 @@
     method public boolean getIncludeFontPadding();
     method public android.os.Bundle getInputExtras(boolean);
     method public int getInputType();
-    method public boolean getJustify();
+    method public int getJustificationMode();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
@@ -55188,7 +55293,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public boolean setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
@@ -55206,7 +55311,7 @@
     method public void setIncludeFontPadding(boolean);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
-    method public void setJustify(boolean);
+    method public void setJustificationMode(int);
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1bafe96..1effe9c 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -290,6 +290,10 @@
     field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
   }
 
+  public static final class FontsContract.Columns implements android.provider.BaseColumns {
+    field public static final java.lang.String STYLE = "font_style";
+  }
+
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 382f5fe..6db91be 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3580,7 +3580,7 @@
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public void enterPictureInPictureMode();
     method public boolean enterPictureInPictureMode(android.app.PictureInPictureArgs);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public void finish();
     method public void finishActivity(int);
     method public void finishActivityFromChild(android.app.Activity, int);
@@ -4370,7 +4370,7 @@
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public android.app.ActionBar getActionBar();
     method public final android.content.Context getContext();
     method public android.view.View getCurrentFocus();
@@ -7074,6 +7074,7 @@
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
     method public boolean isRequestPinAppWidgetSupported();
@@ -8921,7 +8922,6 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
-    field public static final java.lang.String FONT_SERVICE = "font";
     field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
@@ -10684,6 +10684,7 @@
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
     field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
+    field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
     field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
     field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
     field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
@@ -13292,7 +13293,7 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public boolean setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -13826,8 +13827,8 @@
     method public static android.graphics.Typeface.Builder obtain();
     method public void recycle();
     method public void reset();
-    method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String);
-    method public android.graphics.Typeface.Builder setFontVariationSettings(android.text.FontConfig.Axis[]);
+    method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
     method public android.graphics.Typeface.Builder setItalic(int);
     method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
     method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
@@ -14438,6 +14439,21 @@
     field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
   }
 
+  public final class FontVariationAxis implements android.os.Parcelable {
+    ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public int describeContents();
+    method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+    method public float getStyleValue();
+    method public java.lang.String getTag();
+    method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
+  }
+
+  public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
+    ctor public FontVariationAxis.InvalidFormatException(java.lang.String);
+  }
+
 }
 
 package android.graphics.pdf {
@@ -16037,11 +16053,11 @@
     ctor public UsbRequest();
     method public boolean cancel();
     method public void close();
-    method public boolean enqueue(java.nio.ByteBuffer);
     method public java.lang.Object getClientData();
     method public android.hardware.usb.UsbEndpoint getEndpoint();
     method public boolean initialize(android.hardware.usb.UsbDeviceConnection, android.hardware.usb.UsbEndpoint);
     method public deprecated boolean queue(java.nio.ByteBuffer, int);
+    method public boolean queue(java.nio.ByteBuffer);
     method public void setClientData(java.lang.Object);
   }
 
@@ -23112,6 +23128,7 @@
     method public void setProfile(android.media.CamcorderProfile);
     method public void setVideoEncoder(int) throws java.lang.IllegalStateException;
     method public void setVideoEncodingBitRate(int);
+    method public void setVideoEncodingProfileLevel(int, int);
     method public void setVideoFrameRate(int) throws java.lang.IllegalStateException;
     method public void setVideoSize(int, int) throws java.lang.IllegalStateException;
     method public void setVideoSource(int) throws java.lang.IllegalStateException;
@@ -24653,85 +24670,6 @@
     field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
   }
 
-  public static abstract interface TvContract.BasePreviewProgramColumns implements android.media.tv.TvContract.BaseProgramColumns {
-    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
-    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
-    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
-    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
-    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
-    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
-    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
-    field public static final java.lang.String COLUMN_AUTHOR = "author";
-    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
-    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
-    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
-    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
-    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
-    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
-    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
-    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
-    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
-    field public static final java.lang.String COLUMN_LIVE = "live";
-    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
-    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
-    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
-    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
-    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
-    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
-    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
-    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
-    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
-    field public static final java.lang.String COLUMN_TYPE = "type";
-    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
-    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
-    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
-    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
-    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
-    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
-    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
-    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
-    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
-    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
-    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
-    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
-    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
-    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
-    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
-    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
-    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
-    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
-    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
-    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
-  }
-
-  public static abstract interface TvContract.BaseProgramColumns implements android.media.tv.TvContract.BaseTvColumns {
-    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
-    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
-    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
-    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
-    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
-    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
-    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
-    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
-    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
-    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
-    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
-    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
-    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
-    field public static final java.lang.String COLUMN_TITLE = "title";
-    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
-    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
-    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
-  }
-
   public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
     field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
   }
@@ -24818,22 +24756,116 @@
     field public static final java.lang.String CONTENT_DIRECTORY = "logo";
   }
 
-  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+  public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+    field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+    field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String COLUMN_WEIGHT = "weight";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preview_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/preview_program";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+    field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+    field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+    field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+    field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+    field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+    field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+    field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+    field public static final int TYPE_ALBUM = 8; // 0x8
+    field public static final int TYPE_ARTIST = 9; // 0x9
+    field public static final int TYPE_CHANNEL = 6; // 0x6
+    field public static final int TYPE_CLIP = 4; // 0x4
+    field public static final int TYPE_EVENT = 5; // 0x5
+    field public static final int TYPE_MOVIE = 0; // 0x0
+    field public static final int TYPE_PLAYLIST = 10; // 0xa
+    field public static final int TYPE_STATION = 11; // 0xb
+    field public static final int TYPE_TRACK = 7; // 0x7
+    field public static final int TYPE_TV_EPISODE = 3; // 0x3
+    field public static final int TYPE_TV_SEASON = 2; // 0x2
+    field public static final int TYPE_TV_SERIES = 1; // 0x1
   }
 
-  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseProgramColumns {
+  public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
     field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
     field public static final android.net.Uri CONTENT_URI;
@@ -24862,32 +24894,126 @@
     field public static final java.lang.String TRAVEL = "TRAVEL";
   }
 
-  public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseProgramColumns {
+  public static final class TvContract.RecordedPrograms implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
     field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
     field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_RECORDING_DATA_BYTES = "recording_data_bytes";
     field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
     field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
     field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
     field public static final android.net.Uri CONTENT_URI;
   }
 
-  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BasePreviewProgramColumns {
+  public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
     ctor public TvContract.WatchNextPrograms();
+    field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
+    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
+    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
+    field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
+    field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
+    field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
+    field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+    field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+    field public static final java.lang.String COLUMN_CONTENT_ID = "content_id";
+    field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
+    field public static final java.lang.String COLUMN_DURATION_MILLIS = "duration_millis";
+    field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
+    field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTENT_URI = "intent_uri";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
+    field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
     field public static final java.lang.String COLUMN_LAST_ENGAGEMENT_TIME_UTC_MILLIS = "last_engagement_time_utc_millis";
+    field public static final java.lang.String COLUMN_LAST_PLAYBACK_POSITION_MILLIS = "last_playback_position_millis";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO_URI = "logo_uri";
+    field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+    field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+    field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+    field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+    field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
+    field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
+    field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+    field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
+    field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
+    field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+    field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
+    field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
     field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/watch_next_program";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
-    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
-    field public static final java.lang.String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+    field public static final int INTERACTION_TYPE_FANS = 3; // 0x3
+    field public static final int INTERACTION_TYPE_FOLLOWERS = 2; // 0x2
+    field public static final int INTERACTION_TYPE_LIKES = 4; // 0x4
+    field public static final int INTERACTION_TYPE_LISTENS = 1; // 0x1
+    field public static final int INTERACTION_TYPE_THUMBS = 5; // 0x5
+    field public static final int INTERACTION_TYPE_VIEWERS = 6; // 0x6
+    field public static final int INTERACTION_TYPE_VIEWS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+    field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+    field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
+    field public static final int TYPE_ALBUM = 8; // 0x8
+    field public static final int TYPE_ARTIST = 9; // 0x9
+    field public static final int TYPE_CHANNEL = 6; // 0x6
+    field public static final int TYPE_CLIP = 4; // 0x4
+    field public static final int TYPE_EVENT = 5; // 0x5
+    field public static final int TYPE_MOVIE = 0; // 0x0
+    field public static final int TYPE_PLAYLIST = 10; // 0xa
+    field public static final int TYPE_STATION = 11; // 0xb
+    field public static final int TYPE_TRACK = 7; // 0x7
+    field public static final int TYPE_TV_EPISODE = 3; // 0x3
+    field public static final int TYPE_TV_SEASON = 2; // 0x2
+    field public static final int TYPE_TV_SERIES = 1; // 0x1
+    field public static final int WATCH_NEXT_TYPE_CONTINUE = 0; // 0x0
+    field public static final int WATCH_NEXT_TYPE_NEW = 2; // 0x2
+    field public static final int WATCH_NEXT_TYPE_NEXT = 1; // 0x1
+    field public static final int WATCH_NEXT_TYPE_WATCHLIST = 3; // 0x3
   }
 
   public final class TvInputInfo implements android.os.Parcelable {
@@ -34535,14 +34661,15 @@
 
   public static final class FontsContract.Columns implements android.provider.BaseColumns {
     ctor public FontsContract.Columns();
+    field public static final java.lang.String ITALIC = "font_italic";
     field public static final java.lang.String RESULT_CODE = "result_code";
     field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
     field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
     field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
     field public static final int RESULT_CODE_OK = 0; // 0x0
-    field public static final java.lang.String STYLE = "font_style";
     field public static final java.lang.String TTC_INDEX = "font_ttc_index";
     field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+    field public static final java.lang.String WEIGHT = "font_weight";
   }
 
   public final deprecated class LiveFolders implements android.provider.BaseColumns {
@@ -38828,6 +38955,7 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public final long getConnectTimeMillis();
+    method public long getCreationTimeMillis();
     method public android.telecom.DisconnectCause getDisconnectCause();
     method public android.os.Bundle getExtras();
     method public android.telecom.GatewayInfo getGatewayInfo();
@@ -41258,65 +41386,6 @@
     method public android.text.Editable newEditable(java.lang.CharSequence);
   }
 
-  public final class FontConfig implements android.os.Parcelable {
-    ctor public FontConfig(android.text.FontConfig.Family[], android.text.FontConfig.Alias[]);
-    method public int describeContents();
-    method public android.text.FontConfig.Alias[] getAliases();
-    method public android.text.FontConfig.Family[] getFamilies();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR;
-  }
-
-  public static final class FontConfig.Alias implements android.os.Parcelable {
-    ctor public FontConfig.Alias(java.lang.String, java.lang.String, int);
-    method public int describeContents();
-    method public java.lang.String getName();
-    method public java.lang.String getToName();
-    method public int getWeight();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR;
-  }
-
-  public static final class FontConfig.Axis implements android.os.Parcelable {
-    ctor public FontConfig.Axis(int, float);
-    ctor public FontConfig.Axis(java.lang.String, float);
-    method public int describeContents();
-    method public float getStyleValue();
-    method public int getTag();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR;
-  }
-
-  public static final class FontConfig.Family implements android.os.Parcelable {
-    ctor public FontConfig.Family(java.lang.String, android.text.FontConfig.Font[], java.lang.String, int);
-    method public int describeContents();
-    method public android.text.FontConfig.Font[] getFonts();
-    method public java.lang.String getLanguage();
-    method public java.lang.String getName();
-    method public int getVariant();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR;
-    field public static final int VARIANT_COMPACT = 1; // 0x1
-    field public static final int VARIANT_DEFAULT = 0; // 0x0
-    field public static final int VARIANT_ELEGANT = 2; // 0x2
-  }
-
-  public static final class FontConfig.Font implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.text.FontConfig.Axis[] getAxes();
-    method public java.lang.String getFontName();
-    method public int getTtcIndex();
-    method public android.net.Uri getUri();
-    method public int getWeight();
-    method public boolean isItalic();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR;
-  }
-
-  public final class FontManager {
-    method public android.text.FontConfig getSystemFonts();
-  }
-
   public abstract interface GetChars implements java.lang.CharSequence {
     method public abstract void getChars(int, int, char[], int);
   }
@@ -41464,6 +41533,8 @@
     field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
     field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
     field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
+    field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
   }
 
   public static final class Layout.Alignment extends java.lang.Enum {
@@ -41665,7 +41736,7 @@
     method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
     method public android.text.StaticLayout.Builder setIncludePad(boolean);
     method public android.text.StaticLayout.Builder setIndents(int[], int[]);
-    method public android.text.StaticLayout.Builder setJustify(boolean);
+    method public android.text.StaticLayout.Builder setJustificationMode(int);
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46918,7 +46989,7 @@
     method public void clearFlags(int);
     method public abstract void closeAllPanels();
     method public abstract void closePanel(int);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public boolean getAllowEnterTransitionOverlap();
     method public boolean getAllowReturnTransitionOverlap();
     method public final android.view.WindowManager.LayoutParams getAttributes();
@@ -49045,7 +49116,7 @@
     method public abstract boolean getOffscreenPreRaster();
     method public abstract deprecated android.webkit.WebSettings.PluginState getPluginState();
     method public abstract java.lang.String getSansSerifFontFamily();
-    method public abstract boolean getSaveFormData();
+    method public abstract deprecated boolean getSaveFormData();
     method public abstract deprecated boolean getSavePassword();
     method public abstract java.lang.String getSerifFontFamily();
     method public abstract java.lang.String getStandardFontFamily();
@@ -49094,7 +49165,7 @@
     method public abstract deprecated void setPluginState(android.webkit.WebSettings.PluginState);
     method public abstract deprecated void setRenderPriority(android.webkit.WebSettings.RenderPriority);
     method public abstract void setSansSerifFontFamily(java.lang.String);
-    method public abstract void setSaveFormData(boolean);
+    method public abstract deprecated void setSaveFormData(boolean);
     method public abstract deprecated void setSavePassword(boolean);
     method public abstract void setSerifFontFamily(java.lang.String);
     method public abstract void setStandardFontFamily(java.lang.String);
@@ -49385,12 +49456,12 @@
 
   public abstract class WebViewDatabase {
     ctor public WebViewDatabase();
-    method public abstract void clearFormData();
+    method public abstract deprecated void clearFormData();
     method public abstract void clearHttpAuthUsernamePassword();
     method public abstract deprecated void clearUsernamePassword();
     method public abstract java.lang.String[] getHttpAuthUsernamePassword(java.lang.String, java.lang.String);
     method public static android.webkit.WebViewDatabase getInstance(android.content.Context);
-    method public abstract boolean hasFormData();
+    method public abstract deprecated boolean hasFormData();
     method public abstract boolean hasHttpAuthUsernamePassword();
     method public abstract deprecated boolean hasUsernamePassword();
     method public abstract void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
@@ -51658,7 +51729,7 @@
     method public boolean getIncludeFontPadding();
     method public android.os.Bundle getInputExtras(boolean);
     method public int getInputType();
-    method public boolean getJustify();
+    method public int getJustificationMode();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
@@ -51753,7 +51824,7 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public boolean setFontVariationSettings(java.lang.String);
+    method public boolean setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
@@ -51771,7 +51842,7 @@
     method public void setIncludeFontPadding(boolean);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
-    method public void setJustify(boolean);
+    method public void setJustificationMode(int);
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 42b2ae6..d20c08c 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -296,6 +296,10 @@
     field public static final deprecated java.lang.String TIMESTAMP = "timestamp";
   }
 
+  public static final class FontsContract.Columns implements android.provider.BaseColumns {
+    field public static final java.lang.String STYLE = "font_style";
+  }
+
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final deprecated java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
   }
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 3a92b9e..0e2c13e 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -26,7 +26,8 @@
     libGLESv1_CM \
     libgui \
     libOpenSLES \
-    libtinyalsa
+    libtinyalsa \
+    libbase
 
 LOCAL_MODULE:= bootanimation
 
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a6d2986..7394490 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -38,6 +38,8 @@
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 
+#include <android-base/properties.h>
+
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -67,6 +69,9 @@
 static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
 static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
 static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
+static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
+static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";
+
 static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
 static const char SYSTEM_TIME_DIR_NAME[] = "time";
 static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
@@ -106,7 +111,13 @@
     mSession = new SurfaceComposerClient();
 
     // If the system has already booted, the animation is not being used for a boot.
-    mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
+    mSystemBoot = !android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false);
+    std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
+    if (powerCtl.empty()) {
+        mShuttingDown = false;
+    } else {
+        mShuttingDown = true;
+    }
 }
 
 void BootAnimation::onFirstRef() {
@@ -314,16 +325,23 @@
     char decrypt[PROPERTY_VALUE_MAX];
     property_get("vold.decrypt", decrypt, "");
 
-    bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
+    bool encryptedAnimation = atoi(decrypt) != 0 ||
+        !strcmp("trigger_restart_min_framework", decrypt);
 
-    if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
+    if (!mShuttingDown && encryptedAnimation &&
+        (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
         mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
+        return NO_ERROR;
     }
-    else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) {
-        mZipFileName = OEM_BOOTANIMATION_FILE;
-    }
-    else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) {
-        mZipFileName = SYSTEM_BOOTANIMATION_FILE;
+    static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
+    static const char* shutdownFiles[] =
+        {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+
+    for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
+        if (access(f, R_OK) == 0) {
+            mZipFileName = f;
+            return NO_ERROR;
+        }
     }
     return NO_ERROR;
 }
@@ -352,7 +370,8 @@
 
 bool BootAnimation::android()
 {
-    ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
+    ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+            elapsedRealtime());
     initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
     initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
 
@@ -878,7 +897,8 @@
     const int animationX = (mWidth - animation.width) / 2;
     const int animationY = (mHeight - animation.height) / 2;
 
-    ALOGD("BootAnimationShownTiming start time: %" PRId64 "ms", elapsedRealtime());
+    ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+            elapsedRealtime());
     for (size_t i=0 ; i<pcount ; i++) {
         const Animation::Part& part(animation.parts[i]);
         const size_t fcount = part.frames.size();
@@ -1047,7 +1067,9 @@
     if (!mSystemBoot) {
         return false;
     }
-
+    if (mShuttingDown) { // no audio while shutting down
+        return false;
+    }
     // Read the system property to see if we should play the sound.
     // If it's not present, default to allowed.
     if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
@@ -1073,7 +1095,7 @@
     if (mTimeIsAccurate) {
         return true;
     }
-
+    if (mShuttingDown) return true;
     struct stat statResult;
 
     if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) {
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f1fc98e..181ef1c 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -163,6 +163,7 @@
     bool        mTimeIsAccurate;
     bool        mTimeFormat12Hour;
     bool        mSystemBoot;
+    bool        mShuttingDown;
     String8     mZipFileName;
     SortedVector<String8> mLoadedFiles;
     sp<TimeCheckThread> mTimeCheckThread = nullptr;
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 7344ba7..469c964 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -1,7 +1,7 @@
 service bootanim /system/bin/bootanimation
-    class core
+    class core animation
     user graphics
     group graphics audio
     disabled
     oneshot
-    writepid /dev/stune/top-app/tasks
\ No newline at end of file
+    writepid /dev/stune/top-app/tasks
diff --git a/compiled-classes-phone b/compiled-classes-phone
index ea8f4a4..1a19b2c 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -4061,7 +4061,6 @@
 android.text.FontConfig$Family$1
 android.text.FontConfig$Font
 android.text.FontConfig$Font$1
-android.text.FontManager
 android.text.GetChars
 android.text.GraphicsOperations
 android.text.Html
@@ -5501,8 +5500,6 @@
 com.android.internal.content.PackageMonitor
 com.android.internal.content.ReferrerIntent
 com.android.internal.content.ReferrerIntent$1
-com.android.internal.font.IFontManager
-com.android.internal.font.IFontManager$Stub
 com.android.internal.graphics.drawable.AnimationScaleListDrawable
 com.android.internal.graphics.drawable.AnimationScaleListDrawable$AnimationScaleListState
 com.android.internal.hardware.AmbientDisplayConfiguration
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dbf81f9..c0505eb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2443,13 +2443,20 @@
     }
 
     /**
-     * Finds a view that was identified by the id attribute from the XML that
-     * was processed in {@link #onCreate}.
+     * Finds a view that was identified by the {@code android:id} XML attribute
+     * that was processed in {@link #onCreate}.
+     * <p>
+     * <strong>Note:</strong> In most cases -- depending on compiler support --
+     * the resulting view is automatically cast to the target class type. If
+     * the target class type is unconstrained, an explicit cast may be
+     * necessary.
      *
-     * @return The view if found or null otherwise.
+     * @param id the ID to search for
+     * @return a view with given ID if found, or {@code null} otherwise
+     * @see View#findViewById(int)
      */
     @Nullable
-    public View findViewById(@IdRes int id) {
+    public <T extends View> T findViewById(@IdRes int id) {
         return getWindow().findViewById(id);
     }
 
@@ -4159,14 +4166,25 @@
                 mTaskDescription.setPrimaryColor(colorPrimary);
             }
         }
-        // For dev-preview only.
-        if (mTaskDescription.getBackgroundColor() == 0) {
-            int colorBackground = a.getColor(
-                    com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
-            if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
-                mTaskDescription.setBackgroundColor(colorBackground);
-            }
+
+        int colorBackground = a.getColor(
+                com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
+        if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
+            mTaskDescription.setBackgroundColor(colorBackground);
         }
+
+        final int statusBarColor = a.getColor(
+                com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0);
+        if (statusBarColor != 0) {
+            mTaskDescription.setStatusBarColor(statusBarColor);
+        }
+
+        final int navigationBarColor = a.getColor(
+                com.android.internal.R.styleable.ActivityTaskDescription_navigationBarColor, 0);
+        if (navigationBarColor != 0) {
+            mTaskDescription.setNavigationBarColor(navigationBarColor);
+        }
+
         a.recycle();
         setTaskDescription(mTaskDescription);
     }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4004bd6..aede1bb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1145,6 +1145,8 @@
         private String mIconFilename;
         private int mColorPrimary;
         private int mColorBackground;
+        private int mStatusBarColor;
+        private int mNavigationBarColor;
 
         /**
          * Creates the TaskDescription to the specified values.
@@ -1155,7 +1157,7 @@
          *                     opaque.
          */
         public TaskDescription(String label, Bitmap icon, int colorPrimary) {
-            this(label, icon, null, colorPrimary, 0);
+            this(label, icon, null, colorPrimary, 0, 0, 0);
             if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
                 throw new RuntimeException("A TaskDescription's primary color should be opaque");
             }
@@ -1168,7 +1170,7 @@
          * @param icon An icon that represents the current state of this activity.
          */
         public TaskDescription(String label, Bitmap icon) {
-            this(label, icon, null, 0, 0);
+            this(label, icon, null, 0, 0, 0, 0);
         }
 
         /**
@@ -1177,24 +1179,26 @@
          * @param label A label and description of the current state of this activity.
          */
         public TaskDescription(String label) {
-            this(label, null, null, 0, 0);
+            this(label, null, null, 0, 0, 0, 0);
         }
 
         /**
          * Creates an empty TaskDescription.
          */
         public TaskDescription() {
-            this(null, null, null, 0, 0);
+            this(null, null, null, 0, 0, 0, 0);
         }
 
         /** @hide */
         public TaskDescription(String label, Bitmap icon, String iconFilename, int colorPrimary,
-                int colorBackground) {
+                int colorBackground, int statusBarColor, int navigationBarColor) {
             mLabel = label;
             mIcon = icon;
             mIconFilename = iconFilename;
             mColorPrimary = colorPrimary;
             mColorBackground = colorBackground;
+            mStatusBarColor = statusBarColor;
+            mNavigationBarColor = navigationBarColor;
         }
 
         /**
@@ -1214,6 +1218,8 @@
             mIconFilename = other.mIconFilename;
             mColorPrimary = other.mColorPrimary;
             mColorBackground = other.mColorBackground;
+            mStatusBarColor = other.mStatusBarColor;
+            mNavigationBarColor = other.mNavigationBarColor;
         }
 
         private TaskDescription(Parcel source) {
@@ -1253,6 +1259,20 @@
         }
 
         /**
+         * @hide
+         */
+        public void setStatusBarColor(int statusBarColor) {
+            mStatusBarColor = statusBarColor;
+        }
+
+        /**
+         * @hide
+         */
+        public void setNavigationBarColor(int navigationBarColor) {
+            mNavigationBarColor = navigationBarColor;
+        }
+
+        /**
          * Sets the icon for this task description.
          * @hide
          */
@@ -1325,6 +1345,20 @@
             return mColorBackground;
         }
 
+        /**
+         * @hide
+         */
+        public int getStatusBarColor() {
+            return mStatusBarColor;
+        }
+
+        /**
+         * @hide
+         */
+        public int getNavigationBarColor() {
+            return mNavigationBarColor;
+        }
+
         /** @hide */
         public void saveToXml(XmlSerializer out) throws IOException {
             if (mLabel != null) {
@@ -1377,6 +1411,8 @@
             }
             dest.writeInt(mColorPrimary);
             dest.writeInt(mColorBackground);
+            dest.writeInt(mStatusBarColor);
+            dest.writeInt(mNavigationBarColor);
             if (mIconFilename == null) {
                 dest.writeInt(0);
             } else {
@@ -1390,6 +1426,8 @@
             mIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
             mColorPrimary = source.readInt();
             mColorBackground = source.readInt();
+            mStatusBarColor = source.readInt();
+            mNavigationBarColor = source.readInt();
             mIconFilename = source.readInt() > 0 ? source.readString() : null;
         }
 
@@ -1407,7 +1445,9 @@
         public String toString() {
             return "TaskDescription Label: " + mLabel + " Icon: " + mIcon +
                     " IconFilename: " + mIconFilename + " colorPrimary: " + mColorPrimary +
-                    " colorBackground: " + mColorBackground;
+                    " colorBackground: " + mColorBackground +
+                    " statusBarColor: " + mColorBackground +
+                    " navigationBarColor: " + mNavigationBarColor;
         }
     }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d8e5742..7299d6b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -222,6 +222,7 @@
     private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;
 
     private ContextImpl mSystemContext;
+    private ContextImpl mSystemUiContext;
 
     static volatile IPackageManager sPackageManager;
 
@@ -2195,9 +2196,19 @@
         }
     }
 
+    public ContextImpl getSystemUiContext() {
+        synchronized (this) {
+            if (mSystemUiContext == null) {
+                mSystemUiContext = ContextImpl.createSystemUiContext(this);
+            }
+            return mSystemUiContext;
+        }
+    }
+
     public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
         synchronized (this) {
             getSystemContext().installSystemApplicationInfo(info, classLoader);
+            getSystemUiContext().installSystemApplicationInfo(info, classLoader);
 
             // give ourselves a default profiler
             mProfiler = new Profiler();
@@ -5036,6 +5047,11 @@
             if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
                 systemTheme.rebase();
             }
+
+            final Theme systemUiTheme = getSystemUiContext().getTheme();
+            if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
+                systemUiTheme.rebase();
+            }
         }
 
         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
@@ -5091,9 +5107,10 @@
 
         // Trigger a regular Configuration change event, only with a different assetsSeq number
         // so that we actually call through to all components.
+        // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to
+        // store configurations per-process.
         Configuration newConfig = new Configuration();
-        newConfig.unset();
-        newConfig.assetsSeq = mConfiguration.assetsSeq + 1;
+        newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
         handleConfigurationChanged(newConfig, null);
 
         // Schedule all activities to reload
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 461f9cc..a6838f8b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1352,7 +1352,7 @@
     public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
             throws NameNotFoundException {
         if (app.packageName.equals("system")) {
-            return mContext.mMainThread.getSystemContext().getResources();
+            return mContext.mMainThread.getSystemUiContext().getResources();
         }
         final boolean sameUid = (app.uid == Process.myUid());
         final Resources r = mContext.mMainThread.getTopLevelResources(
@@ -1383,7 +1383,7 @@
                     "Call does not support special user #" + userId);
         }
         if ("system".equals(appPackageName)) {
-            return mContext.mMainThread.getSystemContext().getResources();
+            return mContext.mMainThread.getSystemUiContext().getResources();
         }
         try {
             ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, sDefaultFlags, userId);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5a7246a..75f9d67 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2218,6 +2218,18 @@
         return context;
     }
 
+    /**
+     * System Context to be used for UI. This Context has resources that can be themed.
+     */
+    static ContextImpl createSystemUiContext(ActivityThread mainThread) {
+        LoadedApk packageInfo = new LoadedApk(mainThread);
+        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
+                null);
+        context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
+                packageInfo.getCompatibilityInfo()));
+        return context;
+    }
+
     static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 72ccf72..943c572 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -498,14 +498,22 @@
     }
 
     /**
-     * Finds a child view with the given identifier. Returns null if the
-     * specified child view does not exist or the dialog has not yet been fully
-     * created (for example, via {@link #show()} or {@link #create()}).
+     * Finds the first descendant view with the given ID or {@code null} if the
+     * ID is invalid (< 0), there is no matching view in the hierarchy, or the
+     * dialog has not yet been fully created (for example, via {@link #show()}
+     * or {@link #create()}).
+     * <p>
+     * <strong>Note:</strong> In most cases -- depending on compiler support --
+     * the resulting view is automatically cast to the target class type. If
+     * the target class type is unconstrained, an explicit cast may be
+     * necessary.
      *
-     * @param id the identifier of the view to find
-     * @return The view with the given id or null.
+     * @param id the ID to search for
+     * @return a view with given ID if found, or {@code null} otherwise
+     * @see View#findViewById(int)
      */
-    public @Nullable View findViewById(@IdRes int id) {
+    @Nullable
+    public <T extends View> T findViewById(@IdRes int id) {
         return mWindow.findViewById(id);
     }
 
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 462f66f..b89c165 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -321,6 +322,11 @@
      */
     public static final String EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS = "extra_click_download_ids";
 
+    /** {@hide} */
+    @SystemApi
+    public static final String ACTION_DOWNLOAD_COMPLETED =
+            "android.intent.action.DOWNLOAD_COMPLETED";
+
     /**
      * columns to request from DownloadProvider.
      * @hide
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 279b900..399987f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1128,8 +1128,13 @@
             newState = Fragment.CREATED;
         }
         if (f.mRemoving && newState > f.mState) {
-            // While removing a fragment, we can't change it to a higher state.
-            newState = f.mState;
+            if (f.mState == Fragment.INITIALIZING && f.isInBackStack()) {
+                // Allow the fragment to be created so that it can be saved later.
+                newState = Fragment.CREATED;
+            } else {
+                // While removing a fragment, we can't change it to a higher state.
+                newState = f.mState;
+            }
         }
         // Defer start if requested; don't allow it to move to STARTED or higher
         // if it's not already started.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3d66135..161dd25 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3793,9 +3793,9 @@
                 // Ambient view does not have these
                 bindHeaderText(contentView);
                 bindHeaderChronometerAndTime(contentView);
-                bindExpandButton(contentView);
                 bindProfileBadge(contentView);
             }
+            bindExpandButton(contentView);
         }
 
         private void bindExpandButton(RemoteViews contentView) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index b42df5e..489a0f0 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -984,7 +984,7 @@
                 final ResourcesKey key = mResourceImpls.keyAt(i);
                 final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
                 final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
-                if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
+                if (impl != null && (key.mResDir == null || key.mResDir.equals(baseCodePath))) {
                     updatedResourceKeys.put(impl, new ResourcesKey(
                             key.mResDir,
                             key.mSplitResDirs,
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f719749..6b05bdf 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -125,7 +125,6 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.text.FontManager;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -141,7 +140,6 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.app.ISoundTriggerService;
 import com.android.internal.appwidget.IAppWidgetService;
-import com.android.internal.font.IFontManager;
 import com.android.internal.os.IDropBoxManagerService;
 import com.android.internal.policy.PhoneLayoutInflater;
 
@@ -820,14 +818,6 @@
                 return new IncidentManager(ctx);
             }});
 
-        registerService(Context.FONT_SERVICE, FontManager.class,
-                new CachedServiceFetcher<FontManager>() {
-                    @Override
-                    public FontManager createService(ContextImpl ctx)
-                            throws ServiceNotFoundException {
-                        IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE);
-                        return new FontManager(IFontManager.Stub.asInterface(b));
-                    }});
         registerService(Context.AUTOFILL_MANAGER_SERVICE, AutofillManager.class,
                 new CachedServiceFetcher<AutofillManager>() {
             @Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2f0a630..82ad825 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -697,8 +697,8 @@
             "android.app.extra.PROVISIONING_ORGANIZATION_NAME";
 
     /**
-     * A String extra holding a url to the website of the device's provider. The website can be
-     * opened in a browser during provisioning.
+     * A String extra holding a url to the website of the device provider so the user can open it
+     * during provisioning. If the url is not HTTPS, an error will be shown.
      *
      * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}
      *
@@ -2768,9 +2768,11 @@
      * or clears the lockscreen password.
      * <p>
      * <em>This token is highly sensitive and should be treated at the same level as user
-     * credentials. In particular, NEVER store this token on device in plaintext, especially in
-     * Device-Encrypted storage if the token will be used to reset password on FBE devices before
-     * user unlocks.
+     * credentials. In particular, NEVER store this token on device in plaintext. Do not store
+     * the plaintext token in device-encrypted storage if it will be needed to reset password on
+     * file-based encryption devices before user unlocks. Consider carefully how any password token
+     * will be stored on your server and who will need access to them. Tokens may be the subject of
+     * legal access requests.
      * </em>
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 7d2db5c..fe51633 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -27,9 +27,6 @@
 import android.view.ViewStructure.HtmlInfo.Builder;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
@@ -920,15 +917,6 @@
         }
 
         /**
-         * @hide
-         * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
-         */
-        @Deprecated
-        public AutoFillId getAutoFillId() {
-            return AutoFillId.forDaRealId(mAutofillId);
-        }
-
-        /**
          * Gets the id that can be used to autofill the view contents.
          *
          * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
@@ -939,26 +927,6 @@
         }
 
         /**
-         * @hide
-         * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype()
-         */
-        @Deprecated
-        public AutoFillType getAutoFillType() {
-            switch (getAutofillType()) {
-                case View.AUTOFILL_TYPE_TEXT:
-                    return AutoFillType.forText();
-                case View.AUTOFILL_TYPE_TOGGLE:
-                    return AutoFillType.forToggle();
-                case View.AUTOFILL_TYPE_LIST:
-                    return AutoFillType.forList();
-                case View.AUTOFILL_TYPE_DATE:
-                    return AutoFillType.forDate();
-                default:
-                    return null;
-            }
-        }
-
-        /**
          * Gets the the type of value that can be used to autofill the view contents.
          *
          * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
@@ -982,15 +950,6 @@
         }
 
         /**
-         * @hide
-         * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
-         */
-        @Deprecated
-        public AutoFillValue getAutoFillValue() {
-            return AutoFillValue.forDaRealValue(mAutofillValue);
-        }
-
-        /**
          * Gets the the value of this view.
          *
          * <p>It's only set when the {@link AssistStructure} is used for autofilling purposes, not
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 74a39e8..9f35e85 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -710,9 +710,9 @@
      * user may have a corporate profile. In this case the parent user profile has a
      * child profile, the corporate one.
      *
-     * @param profile The profile for which to get providers. Passing null is equivaled
-     *         to passing only the current user handle.
-     * @return The intalled providers.
+     * @param profile The profile for which to get providers. Passing null is equivalent
+     *        to querying for only the calling user.
+     * @return The installed providers.
      *
      * @see android.os.Process#myUserHandle()
      * @see android.os.UserManager#getUserProfiles()
@@ -722,7 +722,31 @@
             return Collections.emptyList();
         }
         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
-                profile);
+                profile, null);
+    }
+
+    /**
+     * Gets the AppWidget providers for the given package and user profile. User
+     * profile can only be the current user or a profile of the current user. For
+     * example, the current user may have a corporate profile. In this case the
+     * parent user profile has a child profile, the corporate one.
+     *
+     * @param packageName The package for which to get providers. If null, this method is
+     *        equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}.
+     * @param profile The profile for which to get providers. Passing null is equivalent
+     *        to querying for only the calling user.
+     * @return The installed providers.
+     *
+     * @see android.os.Process#myUserHandle()
+     * @see android.os.UserManager#getUserProfiles()
+     */
+    public List<AppWidgetProviderInfo> getInstalledProvidersForPackage(@Nullable String packageName,
+            @Nullable UserHandle profile) {
+        if (mService == null) {
+            return Collections.emptyList();
+        }
+        return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+                profile, packageName);
     }
 
     /**
@@ -733,7 +757,7 @@
             return Collections.emptyList();
         }
         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
-                null);
+                null, null);
     }
 
     /**
@@ -752,7 +776,7 @@
         if (mService == null) {
             return Collections.emptyList();
         }
-        return getInstalledProvidersForProfile(categoryFilter, null);
+        return getInstalledProvidersForProfile(categoryFilter, null, null);
     }
 
     /**
@@ -766,6 +790,7 @@
      * @param profile A profile of the current user which to be queried. The user
      *        is itself also a profile. If null, the providers only for the current user
      *        are returned.
+     * @param packageName If specified, will only return providers from the given package.
      * @return The intalled providers.
      *
      * @see android.os.Process#myUserHandle()
@@ -774,7 +799,7 @@
      * @hide
      */
     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
-            UserHandle profile) {
+            @Nullable UserHandle profile, @Nullable String packageName) {
         if (mService == null) {
             return Collections.emptyList();
         }
@@ -785,7 +810,7 @@
 
         try {
             ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
-                    categoryFilter, profile.getIdentifier());
+                    categoryFilter, profile.getIdentifier(), packageName);
             if (providers == null) {
                 return Collections.emptyList();
             }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index dbbfe30..368c7b8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3870,11 +3870,6 @@
     public static final String DEVICE_IDENTIFIERS_SERVICE = "device_identifiers";
 
     /**
-     * Service that provides System font data.
-     */
-    public static final String FONT_SERVICE = "font";
-
-    /**
      * Service to report a system health "incident"
      * @hide
      */
@@ -4631,4 +4626,18 @@
     public Handler getMainThreadHandler() {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
+
+    /**
+     * Throws an exception if the Context is using system resources,
+     * which are non-runtime-overlay-themable and may show inconsistent UI.
+     * @hide
+     */
+    public void assertRuntimeOverlayThemable() {
+        // Resources.getSystem() is a singleton and the only Resources not managed by
+        // ResourcesManager; therefore Resources.getSystem() is not themable.
+        if (getResources() == Resources.getSystem()) {
+            throw new IllegalArgumentException("Non-UI context used to display UI; "
+                    + "get a UI context from ActivityThread#getSystemUiContext()");
+        }
+    }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index da887af..5415eb5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1505,22 +1505,38 @@
     public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
 
     /**
-     * Activity Action: Launch ephemeral installer.
-     * <p>
-     * Input: The data must be a http: URI that the ephemeral application is registered
-     * to handle.
+     * @hide
+     * @deprecated Do not use. This will go away.
+     *     Replace with {@link #ACTION_INSTALL_INSTANT_APP_PACKAGE}.
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
+            = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+    /**
+     * Activity Action: Launch instant application installer.
      * <p class="note">
      * This is a protected intent that can only be sent by the system.
      * </p>
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_INSTALL_EPHEMERAL_PACKAGE
-            = "android.intent.action.INSTALL_EPHEMERAL_PACKAGE";
+    public static final String ACTION_INSTALL_INSTANT_APP_PACKAGE
+            = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
 
     /**
-     * Service Action: Resolve ephemeral application.
+     * @hide
+     * @deprecated Do not use. This will go away.
+     *     Replace with {@link #ACTION_RESOLVE_INSTANT_APP_PACKAGE}.
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
+            = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+    /**
+     * Service Action: Resolve instant application.
      * <p>
      * The system will have a persistent connection to this service.
      * This is a protected intent that can only be sent by the system.
@@ -1528,12 +1544,22 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String ACTION_RESOLVE_EPHEMERAL_PACKAGE
-            = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE";
+    public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE
+            = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
 
     /**
-     * Activity Action: Launch ephemeral settings.
+     * @hide
+     * @deprecated Do not use. This will go away.
+     *     Replace with {@link #ACTION_INSTANT_APP_RESOLVER_SETTINGS}.
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
+            = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+    /**
+     * Activity Action: Launch instant app settings.
      *
      * <p class="note">
      * This is a protected intent that can only be sent by the system.
@@ -1541,9 +1567,10 @@
      *
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS
-            = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS";
+    public static final String ACTION_INSTANT_APP_RESOLVER_SETTINGS
+            = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
 
     /**
      * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
@@ -3479,6 +3506,261 @@
     public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
 
     /**
+     * Broadcast Action: indicate that the phone service state has changed.
+     * The intent will have the following extra values:</p>
+     * <p>
+     * @see #EXTRA_VOICE_REG_STATE
+     * @see #EXTRA_DATA_REG_STATE
+     * @see #EXTRA_VOICE_ROAMING_TYPE
+     * @see #EXTRA_DATA_ROAMING_TYPE
+     * @see #EXTRA_OPERATOR_ALPHA_LONG
+     * @see #EXTRA_OPERATOR_ALPHA_SHORT
+     * @see #EXTRA_OPERATOR_NUMERIC
+     * @see #EXTRA_DATA_OPERATOR_ALPHA_LONG
+     * @see #EXTRA_DATA_OPERATOR_ALPHA_SHORT
+     * @see #EXTRA_DATA_OPERATOR_NUMERIC
+     * @see #EXTRA_MANUAL
+     * @see #EXTRA_VOICE_RADIO_TECH
+     * @see #EXTRA_DATA_RADIO_TECH
+     * @see #EXTRA_CSS_INDICATOR
+     * @see #EXTRA_NETWORK_ID
+     * @see #EXTRA_SYSTEM_ID
+     * @see #EXTRA_CDMA_ROAMING_INDICATOR
+     * @see #EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR
+     * @see #EXTRA_EMERGENCY_ONLY
+     * @see #EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION
+     * @see #EXTRA_IS_USING_CARRIER_AGGREGATION
+     * @see #EXTRA_LTE_EARFCN_RSRP_BOOST
+     *
+     * <p class="note">
+     * Requires the READ_PHONE_STATE permission.
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SERVICE_STATE = "android.intent.action.SERVICE_STATE";
+
+    /**
+     * An int extra used with {@link #ACTION_SERVICE_STATE} which indicates voice registration
+     * state.
+     * @see android.telephony.ServiceState#STATE_EMERGENCY_ONLY
+     * @see android.telephony.ServiceState#STATE_IN_SERVICE
+     * @see android.telephony.ServiceState#STATE_OUT_OF_SERVICE
+     * @see android.telephony.ServiceState#STATE_POWER_OFF
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_VOICE_REG_STATE = "voiceRegState";
+
+    /**
+     * An int extra used with {@link #ACTION_SERVICE_STATE} which indicates data registration state.
+     * @see android.telephony.ServiceState#STATE_EMERGENCY_ONLY
+     * @see android.telephony.ServiceState#STATE_IN_SERVICE
+     * @see android.telephony.ServiceState#STATE_OUT_OF_SERVICE
+     * @see android.telephony.ServiceState#STATE_POWER_OFF
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_DATA_REG_STATE = "dataRegState";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} which indicates the voice roaming
+     * type.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_VOICE_ROAMING_TYPE = "voiceRoamingType";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} which indicates the data roaming
+     * type.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_DATA_ROAMING_TYPE = "dataRoamingType";
+
+    /**
+     * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+     * registered voice operator name in long alphanumeric format.
+     * {@code null} if the operator name is not known or unregistered.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_OPERATOR_ALPHA_LONG = "operator-alpha-long";
+
+    /**
+     * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+     * registered voice operator name in short alphanumeric format.
+     * {@code null} if the operator name is not known or unregistered.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_OPERATOR_ALPHA_SHORT = "operator-alpha-short";
+
+    /**
+     * A string extra used with {@link #ACTION_SERVICE_STATE} containing the MCC
+     * (Mobile Country Code, 3 digits) and MNC (Mobile Network code, 2-3 digits) for the mobile
+     * network.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_OPERATOR_NUMERIC = "operator-numeric";
+
+    /**
+     * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+     * registered data operator name in long alphanumeric format.
+     * {@code null} if the operator name is not known or unregistered.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_DATA_OPERATOR_ALPHA_LONG = "data-operator-alpha-long";
+
+    /**
+     * A string extra used with {@link #ACTION_SERVICE_STATE} which represents the current
+     * registered data operator name in short alphanumeric format.
+     * {@code null} if the operator name is not known or unregistered.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_DATA_OPERATOR_ALPHA_SHORT = "data-operator-alpha-short";
+
+    /**
+     * A string extra used with {@link #ACTION_SERVICE_STATE} containing the MCC
+     * (Mobile Country Code, 3 digits) and MNC (Mobile Network code, 2-3 digits) for the
+     * data operator.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_DATA_OPERATOR_NUMERIC = "data-operator-numeric";
+
+    /**
+     * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates whether the current
+     * network selection mode is manual.
+     * Will be {@code true} if manual mode, {@code false} if automatic mode.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_MANUAL = "manual";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the current voice
+     * radio technology.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_VOICE_RADIO_TECH = "radioTechnology";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the current data
+     * radio technology.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_DATA_RADIO_TECH = "dataRadioTechnology";
+
+    /**
+     * A boolean extra used with {@link #ACTION_SERVICE_STATE} which represents concurrent service
+     * support on CDMA network.
+     * Will be {@code true} if support, {@code false} otherwise.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_CSS_INDICATOR = "cssIndicator";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the CDMA network
+     * id. {@code Integer.MAX_VALUE} if unknown.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_NETWORK_ID = "networkId";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} which represents the CDMA system id.
+     * {@code Integer.MAX_VALUE} if unknown.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_SYSTEM_ID = "systemId";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} represents the TSB-58 roaming
+     * indicator if registered on a CDMA or EVDO system or {@code -1} if not.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_CDMA_ROAMING_INDICATOR = "cdmaRoamingIndicator";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} represents the default roaming
+     * indicator from the PRL if registered on a CDMA or EVDO system {@code -1} if not.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_CDMA_DEFAULT_ROAMING_INDICATOR = "cdmaDefaultRoamingIndicator";
+
+    /**
+     * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates if under emergency
+     * only mode.
+     * {@code true} if in emergency only mode, {@code false} otherwise.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
+
+    /**
+     * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates whether data network
+     * registration state is roaming.
+     * {@code true} if registration indicates roaming, {@code false} otherwise
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_IS_DATA_ROAMING_FROM_REGISTRATION =
+            "isDataRoamingFromRegistration";
+
+    /**
+     * A boolean extra used with {@link #ACTION_SERVICE_STATE} which indicates if carrier
+     * aggregation is in use.
+     * {@code true} if carrier aggregation is in use, {@code false} otherwise.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_IS_USING_CARRIER_AGGREGATION = "isUsingCarrierAggregation";
+
+    /**
+     * An integer extra used with {@link #ACTION_SERVICE_STATE} representing the offset which
+     * is reduced from the rsrp threshold while calculating signal strength level.
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    public static final String EXTRA_LTE_EARFCN_RSRP_BOOST = "LteEarfcnRsrpBoost";
+
+    /**
      * The name of the extra used to define the text to be processed, as a
      * CharSequence. Note that this may be a styled CharSequence, so you must use
      * {@link Bundle#getCharSequence(String) Bundle.getCharSequence()} to retrieve it.
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 912ce3d..4d76755 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -419,7 +419,7 @@
      */
     private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
         if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
-            Log.e(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
+            Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
         }
     }
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 136c13b..50e3e68 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1688,6 +1688,10 @@
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
 
+    /** {@hide} */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_CTS = "android.software.cts";
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports one or more methods of
@@ -2158,7 +2162,6 @@
      * {@link #hasSystemFeature}: The device supports only leanback UI. Only
      * applications designed for this experience should be run, though this is
      * not enforced by the system.
-     * @hide
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
@@ -6244,7 +6247,7 @@
      * Return the {@link ComponentName} of the activity providing Settings for the Instant App
      * resolver.
      *
-     * @see {@link android.content.intent#ACTION_EPHEMERAL_RESOLVER_SETTINGS}
+     * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index b276008..e845359 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -102,6 +102,16 @@
             int displayId, DisplayInfo info);
 
     /**
+     * Get current display info without override from WindowManager.
+     * Current implementation of LogicalDisplay#getDisplayInfoLocked() always returns display info
+     * with overrides from WM if set. This method can be used for getting real display size without
+     * overrides to determine if real changes to display metrics happened.
+     * @param displayId Id of the target display.
+     * @param outInfo {@link DisplayInfo} to fill.
+     */
+    public abstract void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo);
+
+    /**
      * Called by the window manager to perform traversals while holding a
      * surface flinger transaction.
      */
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index badb344..239a2df 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -60,9 +60,11 @@
     // Prevent the connection from being finalized
     private UsbDeviceConnection mConnection;
 
-    /** Whether this buffer was {@link #enqueue enqueued (new behavior)} or {@link #queue queued
-     * (deprecared behavior)}. */
-    private boolean mIsUsingEnqueue;
+    /**
+     * Whether this buffer was {@link #queue(ByteBuffer) queued using the new behavior} or
+     * {@link #queue(ByteBuffer, int) queued using the deprecated behavior}.
+     */
+    private boolean mIsUsingNewQueue;
 
     /** Temporary buffer than might be used while buffer is enqueued */
     private ByteBuffer mTempBuffer;
@@ -172,7 +174,7 @@
      *
      * @return true if the queueing operation succeeded
      *
-     * @deprecated Use {@link #enqueue(ByteBuffer)} instead.
+     * @deprecated Use {@link #queue(ByteBuffer)} instead.
      */
     @Deprecated
     public boolean queue(ByteBuffer buffer, int length) {
@@ -219,23 +221,23 @@
      *
      * @return true if the queueing operation succeeded
      */
-    public boolean enqueue(@Nullable ByteBuffer buffer) {
+    public boolean queue(@Nullable ByteBuffer buffer) {
         // Request need to be initialized
         Preconditions.checkState(mNativeContext != 0, "request is not initialized");
 
-        // Request can not be currently enqueued
-        Preconditions.checkState(!mIsUsingEnqueue, "request is currently enqueued");
+        // Request can not be currently queued
+        Preconditions.checkState(!mIsUsingNewQueue, "this request is currently queued");
 
         boolean isSend = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
-        boolean wasEnqueued;
+        boolean wasQueued;
 
         synchronized (mLock) {
             mBuffer = buffer;
 
             if (buffer == null) {
                 // Null buffers enqueue empty USB requests which is supported
-                mIsUsingEnqueue = true;
-                wasEnqueued = native_enqueue(null, 0, 0);
+                mIsUsingNewQueue = true;
+                wasQueued = native_queue(null, 0, 0);
             } else {
                 // Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
                 Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
@@ -260,18 +262,18 @@
                     buffer = mTempBuffer;
                 }
 
-                mIsUsingEnqueue = true;
-                wasEnqueued = native_enqueue(buffer, buffer.position(), buffer.remaining());
+                mIsUsingNewQueue = true;
+                wasQueued = native_queue(buffer, buffer.position(), buffer.remaining());
             }
         }
 
-        if (!wasEnqueued) {
-            mIsUsingEnqueue = false;
+        if (!wasQueued) {
+            mIsUsingNewQueue = false;
             mTempBuffer = null;
             mBuffer = null;
         }
 
-        return wasEnqueued;
+        return wasQueued;
     }
 
     /* package */ void dequeue() {
@@ -279,9 +281,9 @@
         int bytesTransferred;
 
         synchronized (mLock) {
-            if (mIsUsingEnqueue) {
+            if (mIsUsingNewQueue) {
                 bytesTransferred = native_dequeue_direct();
-                mIsUsingEnqueue = false;
+                mIsUsingNewQueue = false;
 
                 if (mBuffer == null) {
                     // Nothing to do
@@ -332,7 +334,7 @@
     private native boolean native_init(UsbDeviceConnection connection, int ep_address,
             int ep_attributes, int ep_max_packet_size, int ep_interval);
     private native void native_close();
-    private native boolean native_enqueue(ByteBuffer buffer, int offset, int length);
+    private native boolean native_queue(ByteBuffer buffer, int offset, int length);
     private native boolean native_queue_array(byte[] buffer, int length, boolean out);
     private native int native_dequeue_array(byte[] buffer, int length, boolean out);
     private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out);
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 495340d..63bbd96 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -38,9 +38,6 @@
 
     boolean isUidForeground(int uid);
 
-    /** Higher priority listener before general event dispatch */
-    void setConnectivityListener(INetworkPolicyListener listener);
-
     void registerListener(INetworkPolicyListener listener);
     void unregisterListener(INetworkPolicyListener listener);
 
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index e5d73e0..b5af766 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -59,19 +59,14 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.AppFuseMount;
 import com.android.internal.os.FuseAppLoop;
-import com.android.internal.os.FuseAppLoop.UnmountedException;
 import com.android.internal.os.FuseUnavailableMountException;
 import com.android.internal.os.RoSystemProperties;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.Preconditions;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
@@ -84,7 +79,6 @@
 import java.util.Objects;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
-import libcore.io.IoUtils;
 
 /**
  * StorageManager is the interface to the systems storage service. The storage
@@ -186,15 +180,6 @@
 
     private static volatile IStorageManager sStorageManager = null;
 
-    // TODO: the location of the primary storage block varies from device to device, so we need to
-    // try the most likely candidates - a long-term solution would be a device-specific vold
-    // function that returns the calculated size.
-    private static final String[] INTERNAL_STORAGE_SIZE_PATHS = {
-            "/sys/block/mmcblk0/size",
-            "/sys/block/sda/size"
-    };
-    private static final int INTERNAL_STORAGE_SECTOR_SIZE = 512;
-
     private final Context mContext;
     private final ContentResolver mResolver;
 
@@ -1011,38 +996,13 @@
 
     /** {@hide} */
     public static Pair<String, Long> getPrimaryStoragePathAndSize() {
-        for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
-            final long numberBlocks = readLong(path);
-            if (numberBlocks > 0) {
-                return new Pair<>(path,
-                        FileUtils.roundStorageSize(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
-            }
-        }
-        return null;
+        return Pair.create(null,
+                FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace()));
     }
 
-
     /** {@hide} */
     public long getPrimaryStorageSize() {
-        final Pair<String, Long> pair = getPrimaryStoragePathAndSize();
-        return pair == null ? 0 : pair.second.longValue();
-    }
-
-    private static long readLong(String path) {
-        try (final FileInputStream fis = new FileInputStream(path);
-                final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
-            return Long.parseLong(reader.readLine());
-        } catch (FileNotFoundException e) {
-            // This is expected since we are trying to parse multiple paths.
-            Slog.i(TAG, "readLong(): Path doesn't exist: " + path + ": " + e);
-            return 0;
-        } catch (NumberFormatException e) {
-            Slog.e(TAG, "readLong(): Could not parse " + path + ": " + e);
-            return 0;
-        } catch (Exception e) {
-            Slog.e(TAG, "readLong(): Unknown exception while opening " + path + ": " + e);
-            return 0;
-       }
+        return FileUtils.roundStorageSize(Environment.getDataDirectory().getTotalSpace());
     }
 
     /** @removed */
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index a280e59..9d83bd7 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -114,7 +114,7 @@
          * download's content: uri is specified in the intent's data.
          */
         public static final String ACTION_DOWNLOAD_COMPLETED =
-                "android.intent.action.DOWNLOAD_COMPLETED";
+                DownloadManager.ACTION_DOWNLOAD_COMPLETED;
 
         /**
          * Broadcast Action: this is sent by the download manager to the app
@@ -127,7 +127,7 @@
          * successfully.
          */
         public static final String ACTION_NOTIFICATION_CLICKED =
-                "android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED";
+                DownloadManager.ACTION_NOTIFICATION_CLICKED;
 
         /**
          * The name of the column containing the URI of the data being downloaded.
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index fd9d4db..4deb4ab 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -72,15 +72,28 @@
          */
         public static final String VARIATION_SETTINGS = "font_variation_settings";
         /**
-         * Constant used to request data from a font provider. The cursor returned from the query
-         * should have this column populated with the int style for the resulting font. This should
-         * be one of {@link android.graphics.Typeface#NORMAL},
-         * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC} or
-         * {@link android.graphics.Typeface#BOLD_ITALIC}
+         * DO NOT USE THIS COLUMN.
+         * This column is kept for preventing demo apps.
+         * TODO: Remove once nobody uses this column.
+         * @hide
+         * @removed
          */
         public static final String STYLE = "font_style";
         /**
          * Constant used to request data from a font provider. The cursor returned from the query
+         * should have this column populated with the int weight for the resulting font. This value
+         * should be between 100 and 900. The most common values are 400 for regular weight and 700
+         * for bold weight.
+         */
+        public static final String WEIGHT = "font_weight";
+        /**
+         * Constant used to request data from a font provider. The cursor returned from the query
+         * should have this column populated with the int italic for the resulting font. This should
+         * be 0 for regular style and 1 for italic.
+         */
+        public static final String ITALIC = "font_italic";
+        /**
+         * Constant used to request data from a font provider. The cursor returned from the query
          * should have this column populated to indicate the result status of the
          * query. This will be checked before any other data in the cursor. Possible values are
          * {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND},
@@ -274,7 +287,7 @@
                 .build();
         try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
                         Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE,
-                        Columns.RESULT_CODE },
+                        Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
                 "query = ?", new String[] { request.getQuery() }, null);) {
             // TODO: Should we restrict the amount of fonts that can be returned?
             // TODO: Write documentation explaining that all results should be from the same family.
@@ -285,6 +298,8 @@
                 final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID);
                 final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX);
                 final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
+                final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT);
+                final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC);
                 final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
                 while (cursor.moveToNext()) {
                     resultCode = resultCodeColumnIndex != -1
@@ -313,9 +328,22 @@
                                 ? cursor.getInt(ttcIndexColumnIndex) : 0;
                         final String variationSettings = vsColumnIndex != -1
                                 ? cursor.getString(vsColumnIndex) : null;
-                        final int style = styleColumnIndex != -1
-                                ? cursor.getInt(styleColumnIndex) : Typeface.NORMAL;
-                        result.add(new FontResult(pfd, ttcIndex, variationSettings, style));
+                        // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
+                        int weight;
+                        boolean italic;
+                        if (weightColumnIndex != -1 && italicColumnIndex != -1) {
+                            weight = cursor.getInt(weightColumnIndex);
+                            italic = cursor.getInt(italicColumnIndex) == 1;
+                        } else if (styleColumnIndex != -1) {
+                            final int style = cursor.getInt(styleColumnIndex);
+                            weight = (style & Typeface.BOLD) != 0 ? 700 : 400;
+                            italic = (style & Typeface.ITALIC) != 0;
+                        } else {
+                            weight = 400;
+                            italic = false;
+                        }
+                        result.add(
+                                new FontResult(pfd, ttcIndex, variationSettings, weight, italic));
                     } catch (FileNotFoundException e) {
                         Log.e(TAG, "FileNotFoundException raised when interacting with content "
                                 + "provider " + authority, e);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e2100bd..660d53a 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10324,6 +10324,10 @@
             INSTANT_APP_SETTINGS.add(DEVELOPMENT_FORCE_RTL);
             INSTANT_APP_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES);
             INSTANT_APP_SETTINGS.add(AIRPLANE_MODE_ON);
+            INSTANT_APP_SETTINGS.add(WINDOW_ANIMATION_SCALE);
+            INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE);
+            INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE);
+            INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES);
         }
 
         /**
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
deleted file mode 100644
index c26f679..0000000
--- a/core/java/android/service/autofill/AutoFillService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2016 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.service.autofill;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use AutofillService
- */
-@Deprecated
-public abstract class AutoFillService extends AutofillService {
-}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 6f17d0e..9f8a621 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -71,7 +71,7 @@
      * Name under which a AutoFillService component publishes information about itself.
      * This meta-data should reference an XML resource containing a
      * <code>&lt;{@link
-     * android.R.styleable#AutoFillService autofill-service}&gt;</code> tag.
+     * android.R.styleable#AutofillService autofill-service}&gt;</code> tag.
      * This is a a sample XML file configuring an AutoFillService:
      * <pre> &lt;autofill-service
      *     android:settingsActivity="foo.bar.SettingsActivity"
diff --git a/core/java/android/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java
index f6d40db..0f4824e 100644
--- a/core/java/android/service/autofill/AutofillServiceInfo.java
+++ b/core/java/android/service/autofill/AutofillServiceInfo.java
@@ -36,7 +36,6 @@
 
 import java.io.IOException;
 
-// TODO(b/33197203 , b/33802548): add CTS tests
 /**
  * {@link ServiceInfo} and meta-data about an {@link AutofillService}.
  *
@@ -75,15 +74,8 @@
         mServiceInfo = si;
         final TypedArray metaDataArray = getMetaDataArray(pm, si);
         if (metaDataArray != null) {
-            // TODO(b/35956626): inline newSettingsActivity once clients migrate
-            final String newSettingsActivity =
-                    metaDataArray.getString(R.styleable.AutofillService_settingsActivity);
-            if (newSettingsActivity != null) {
-                mSettingsActivity = newSettingsActivity;
-            } else {
-                mSettingsActivity =
-                        metaDataArray.getString(R.styleable.AutoFillService_settingsActivity);
-            }
+            mSettingsActivity = metaDataArray
+                    .getString(R.styleable.AutofillService_settingsActivity);
             metaDataArray.recycle();
         } else {
             mSettingsActivity = null;
@@ -96,16 +88,11 @@
     @Nullable
     private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) {
         // Check for permissions.
-        // TODO(b/35956626): remove check for BIND_AUTO_FILL once clients migrate
-        if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)
-                && !Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
+        if (!Manifest.permission.BIND_AUTOFILL.equals(si.permission)) {
             Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTOFILL);
             return null;
         }
 
-        // TODO(b/35956626): remove once clients migrate
-        final boolean oldStyle = !Manifest.permission.BIND_AUTOFILL.equals(si.permission);
-
         // Get the AutoFill metadata, if declared.
         XmlResourceParser parser = si.loadXmlMetaData(pm, AutofillService.SERVICE_META_DATA);
         if (parser == null) {
@@ -141,8 +128,7 @@
                 return null;
             }
 
-            return oldStyle ? res.obtainAttributes(attrs, R.styleable.AutoFillService)
-                    : res.obtainAttributes(attrs, R.styleable.AutofillService);
+            return res.obtainAttributes(attrs, R.styleable.AutofillService);
         } finally {
             parser.close();
         }
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index e27fa06..e77bd0d 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -23,8 +23,6 @@
 import android.content.IntentSender;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.AutoFillValue;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.widget.RemoteViews;
@@ -78,11 +76,6 @@
     }
 
     /** @hide */
-    public @Nullable RemoteViews getPresentation() {
-        return mPresentation;
-    }
-
-    /** @hide */
     public @Nullable IntentSender getAuthentication() {
         return mAuthentication;
     }
@@ -180,15 +173,6 @@
         }
 
         /**
-         * @hide
-         * @deprecated TODO(b/35956626): remove once clients use other setValue()
-         */
-       @Deprecated
-        public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
-            return setValue(id.getDaRealId(), value.getDaRealValue());
-        }
-
-        /**
          * Sets the value of a field.
          *
          * @param id id returned by {@link
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 6213d27..95608a5 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -25,7 +25,6 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.view.autofill.AutoFillId;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
@@ -269,26 +268,6 @@
             return this;
         }
 
-
-        /**
-         * @hide
-         */
-        // TODO(b/33197203): temporary fix to runtime crash
-        public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
-            throwIfDestroyed();
-
-            if (ids == null || ids.length == 0) {
-                return this;
-            }
-            if (mRequiredIds == null) {
-                mRequiredIds = new AutofillId[ids.length];
-            }
-            for (int i = 0; i < ids.length; i++) {
-                mRequiredIds[i] = ids[i].getDaRealId();
-            }
-            return this;
-        }
-
         /**
          * Sets an optional description to be shown in the UI when the user is asked to save.
          *
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 1e9deeb..6208c53 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -85,7 +85,7 @@
         this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 spacingmult, spacingadd, includepad,
                 StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE,
-                false /* justify */, ellipsize, ellipsizedWidth);
+                Layout.JUSTIFICATION_MODE_NONE, ellipsize, ellipsizedWidth);
     }
 
     /**
@@ -102,7 +102,7 @@
                          int width, Alignment align, TextDirectionHeuristic textDir,
                          float spacingmult, float spacingadd,
                          boolean includepad, int breakStrategy, int hyphenationFrequency,
-                         boolean justify, TextUtils.TruncateAt ellipsize,
+                         int justificationMode, TextUtils.TruncateAt ellipsize,
                          int ellipsizedWidth) {
         super((ellipsize == null)
                 ? display
@@ -128,7 +128,7 @@
 
         mIncludePad = includepad;
         mBreakStrategy = breakStrategy;
-        mJustify = justify;
+        mJustificationMode = justificationMode;
         mHyphenationFrequency = hyphenationFrequency;
 
         /*
@@ -303,7 +303,7 @@
                 .setEllipsize(mEllipsizeAt)
                 .setBreakStrategy(mBreakStrategy)
                 .setHyphenationFrequency(mHyphenationFrequency)
-                .setJustify(mJustify);
+                .setJustificationMode(mJustificationMode);
         reflowed.generate(b, false, true);
         int n = reflowed.getLineCount();
         // If the new layout has a blank line at the end, but it is not
@@ -811,7 +811,7 @@
     private TextUtils.TruncateAt mEllipsizeAt;
     private int mBreakStrategy;
     private int mHyphenationFrequency;
-    private boolean mJustify;
+    private int mJustificationMode;
 
     private PackedIntVector mInts;
     private PackedObjectVector<Directions> mObjects;
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 14d3ad7..8537d8f 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -21,7 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.FontListParser;
+import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -31,6 +31,7 @@
 
 /**
  * Font configuration descriptions for System fonts.
+ * @hide
  */
 public final class FontConfig implements Parcelable {
     private final @NonNull Family[] mFamilies;
@@ -84,78 +85,12 @@
     };
 
     /**
-     * Class that holds information about a Font axis.
-     */
-    public static final class Axis implements Parcelable {
-        private final int mTag;
-        private final float mStyleValue;
-
-        public Axis(int tag, float styleValue) {
-            mTag = tag;
-            mStyleValue = styleValue;
-        }
-
-        public Axis(@NonNull String tagString, float styleValue) {
-            if (!FontListParser.isValidTag(tagString)) {
-                throw new IllegalArgumentException("Invalid tag pattern: " + tagString);
-            }
-            mTag = FontListParser.makeTag(tagString);
-            mStyleValue = styleValue;
-        }
-
-        /**
-         * Returns the variable font axis tag associated to this axis.
-         */
-        public int getTag() {
-            return mTag;
-        }
-
-        /**
-         * Returns the style value associated to the given axis for this font.
-         */
-        public float getStyleValue() {
-            return mStyleValue;
-        }
-
-        /**
-         * @hide
-         */
-        public Axis(Parcel in) {
-            mTag = in.readInt();
-            mStyleValue = in.readFloat();
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flag) {
-            out.writeInt(mTag);
-            out.writeFloat(mStyleValue);
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        public static final Creator<Axis> CREATOR = new Creator<Axis>() {
-            @Override
-            public Axis createFromParcel(Parcel in) {
-                return new Axis(in);
-            }
-
-            @Override
-            public Axis[] newArray(int size) {
-                return new Axis[size];
-            }
-        };
-    }
-
-    /**
      * Class that holds information about a Font.
      */
     public static final class Font implements Parcelable {
         private final @NonNull String mFontName;
         private final int mTtcIndex;
-        private final @NonNull Axis[] mAxes;
+        private final @NonNull FontVariationAxis[] mAxes;
         private final int mWeight;
         private final boolean mIsItalic;
         private Uri mUri;
@@ -163,8 +98,8 @@
         /**
          * @hide
          */
-        public Font(@NonNull String fontName, int ttcIndex, @NonNull Axis[] axes, int weight,
-                boolean isItalic) {
+        public Font(@NonNull String fontName, int ttcIndex, @NonNull FontVariationAxis[] axes,
+                int weight, boolean isItalic) {
             mFontName = fontName;
             mTtcIndex = ttcIndex;
             mAxes = axes;
@@ -189,7 +124,7 @@
         /**
          * Returns the list of axes associated to this font.
          */
-        public @NonNull Axis[] getAxes() {
+        public @NonNull FontVariationAxis[] getAxes() {
             return mAxes;
         }
 
@@ -230,7 +165,7 @@
         public Font(Parcel in) {
             mFontName = in.readString();
             mTtcIndex = in.readInt();
-            mAxes = in.createTypedArray(Axis.CREATOR);
+            mAxes = in.createTypedArray(FontVariationAxis.CREATOR);
             mWeight = in.readInt();
             mIsItalic = in.readInt() == 1;
             mUri = in.readTypedObject(Uri.CREATOR);
diff --git a/core/java/android/text/FontManager.java b/core/java/android/text/FontManager.java
deleted file mode 100644
index b61cbf3..0000000
--- a/core/java/android/text/FontManager.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import android.os.RemoteException;
-
-import com.android.internal.font.IFontManager;
-
-/**
- * Interact with the Font service.
- */
-public final class FontManager {
-    private static final String TAG = "FontManager";
-
-    private final IFontManager mService;
-
-    /**
-     * @hide
-     */
-    public FontManager(IFontManager service) {
-        mService = service;
-    }
-
-    /**
-     * Retrieve the system fonts data. This loads the fonts.xml data if needed and loads all system
-     * fonts in to memory, providing file descriptors for them.
-     */
-    public FontConfig getSystemFonts() {
-        try {
-            return mService.getSystemFonts();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-}
diff --git a/core/java/android/view/autofill/AutoFillId.aidl b/core/java/android/text/FontVariationAxis.aidl
similarity index 83%
rename from core/java/android/view/autofill/AutoFillId.aidl
rename to core/java/android/text/FontVariationAxis.aidl
index fc57ce7..d5d52c2 100644
--- a/core/java/android/view/autofill/AutoFillId.aidl
+++ b/core/java/android/text/FontVariationAxis.aidl
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-package android.view.autofill;
+package android.text;
 
-//  @deprecated TODO(b/35956626): remove once clients use AutofillId
-parcelable AutoFillId;
\ No newline at end of file
+parcelable FontVariationAxis;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 53564f0..b47fce8 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -103,6 +103,21 @@
     private static final ParagraphStyle[] NO_PARA_SPANS =
         ArrayUtils.emptyArray(ParagraphStyle.class);
 
+    /** @hide */
+    @IntDef({JUSTIFICATION_MODE_NONE, JUSTIFICATION_MODE_INTER_WORD})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface JustificationMode {}
+
+    /**
+     * Value for justification mode indicating no justification.
+     */
+    public static final int JUSTIFICATION_MODE_NONE = 0;
+
+    /**
+     * Value for justification mode indicating the text is justified by stretching word spacing.
+     */
+    public static final int JUSTIFICATION_MODE_INTER_WORD = 1;
+
     /**
      * Return how wide a layout must be in order to display the specified text with one line per
      * paragraph.
@@ -219,8 +234,8 @@
     }
 
     /** @hide */
-    protected void setJustify(boolean justify) {
-        mJustify = justify;
+    protected void setJustificationMode(@JustificationMode int justificationMode) {
+        mJustificationMode = justificationMode;
     }
 
     /**
@@ -272,7 +287,7 @@
     }
 
     private boolean isJustificationRequired(int lineNum) {
-        if (!mJustify) return false;
+        if (mJustificationMode == JUSTIFICATION_MODE_NONE) return false;
         final int lineEnd = getLineEnd(lineNum);
         return lineEnd < mText.length() && mText.charAt(lineEnd - 1) != '\n';
     }
@@ -2229,7 +2244,7 @@
     private boolean mSpannedText;
     private TextDirectionHeuristic mTextDir;
     private SpanSet<LineBackgroundSpan> mLineBackgroundSpans;
-    private boolean mJustify;
+    private int mJustificationMode;
 
     public static final int DIR_LEFT_TO_RIGHT = 1;
     public static final int DIR_RIGHT_TO_LEFT = -1;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 9a2e0bb..74ff6dc 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -94,7 +94,7 @@
             b.mMaxLines = Integer.MAX_VALUE;
             b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
             b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
-            b.mJustify = false;
+            b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
 
             b.mMeasuredText = MeasuredText.obtain();
             return b;
@@ -321,15 +321,15 @@
         }
 
         /**
-         * Enables or disables paragraph justification. The default value is disabled (false).
-         * If the last line is too short for justification, the last line will be displayed with
-         * the alignment set by {@link #setAlignment}.
+         * Set paragraph justification mode. The default value is
+         * {@link Layout#JUSTIFICATION_MODE_NONE}. If the last line is too short for justification,
+         * the last line will be displayed with the alignment set by {@link #setAlignment}.
          *
-         * @param justify true for enabling and false for disabling paragraph justification.
+         * @param justificationMode justification mode for the paragraph.
          * @return this builder, useful for chaining.
          */
-        public Builder setJustify(boolean justify) {
-            mJustify = justify;
+        public Builder setJustificationMode(@JustificationMode int justificationMode) {
+            mJustificationMode = justificationMode;
             return this;
         }
 
@@ -418,7 +418,7 @@
         int mHyphenationFrequency;
         int[] mLeftIndents;
         int[] mRightIndents;
-        boolean mJustify;
+        int mJustificationMode;
 
         Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
@@ -572,7 +572,7 @@
 
         mLeftIndents = b.mLeftIndents;
         mRightIndents = b.mRightIndents;
-        setJustify(b.mJustify);
+        setJustificationMode(b.mJustificationMode);
 
         generate(b, b.mIncludePad, b.mIncludePad);
     }
@@ -693,7 +693,8 @@
             nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart,
                     firstWidth, firstWidthLineCount, restWidth,
                     variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency,
-                    b.mJustify);
+                    // TODO: Support more justification mode, e.g. letter spacing, stretching.
+                    b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE);
             if (mLeftIndents != null || mRightIndents != null) {
                 // TODO(raph) performance: it would be better to do this once per layout rather
                 // than once per paragraph, but that would require a change to the native
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 3316f3a..aac5baa 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -529,6 +529,18 @@
         }
     }
 
+    /**
+     * Like {@link #getLastFrameTimeNanos}, but always returns the last frame time, not matter
+     * whether callbacks are currently running.
+     * @return The frame start time of the last frame, in the {@link System#nanoTime()} time base.
+     * @hide
+     */
+    public long getLastFrameTimeNanos() {
+        synchronized (mLock) {
+            return USE_FRAME_TIME ? mLastFrameTimeNanos : System.nanoTime();
+        }
+    }
+
     private void scheduleFrameLocked(long now) {
         if (!mFrameScheduled) {
             mFrameScheduled = true;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5494377..6dedbde 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -50,7 +50,7 @@
  * <li>The real display area specifies the part of the display that contains content
  * including the system decorations.  Even so, the real display area may be smaller than the
  * physical size of the display if the window manager is emulating a smaller display
- * using (adb shell am display-size).  Use the following methods to query the
+ * using (adb shell wm size).  Use the following methods to query the
  * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
  * </ul>
  * </p><p>
@@ -947,7 +947,7 @@
      * The size is adjusted based on the current rotation of the display.
      * </p><p>
      * The real size may be smaller than the physical size of the screen when the
-     * window manager is emulating a smaller display (using adb shell am display-size).
+     * window manager is emulating a smaller display (using adb shell wm size).
      * </p>
      *
      * @param outSize Set to the real size of the display.
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index ae1ee42..f3c2421 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -54,7 +54,9 @@
     final Rect mOtherRect = new Rect();
     final Rect mBestCandidateRect = new Rect();
     private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator =
-            new UserSpecifiedFocusComparator();
+            new UserSpecifiedFocusComparator((v) -> v.getNextFocusForwardId());
+    private final UserSpecifiedFocusComparator mUserSpecifiedClusterComparator =
+            new UserSpecifiedFocusComparator((v) -> v.getNextClusterForwardId());
     private final FocusComparator mFocusComparator = new FocusComparator();
 
     private final ArrayList<View> mTempList = new ArrayList<View>();
@@ -118,7 +120,7 @@
      * @return the "effective" root of {@param focused}
      */
     private ViewGroup getEffectiveRoot(ViewGroup root, View focused) {
-        if (focused == null) {
+        if (focused == null || focused == root) {
             return root;
         }
         ViewParent effective = focused.getParent();
@@ -150,6 +152,12 @@
             @Nullable View currentCluster,
             @View.FocusDirection int direction) {
         View next = null;
+        if (currentCluster != null) {
+            next = findNextUserSpecifiedKeyboardNavigationCluster(root, currentCluster, direction);
+            if (next != null) {
+                return next;
+            }
+        }
 
         final ArrayList<View> clusters = mTempList;
         try {
@@ -165,6 +173,16 @@
         return next;
     }
 
+    private View findNextUserSpecifiedKeyboardNavigationCluster(View root, View currentCluster,
+            int direction) {
+        View userSetNextCluster =
+                currentCluster.findUserSetNextKeyboardNavigationCluster(root, direction);
+        if (userSetNextCluster != null && userSetNextCluster.hasFocusable()) {
+            return userSetNextCluster;
+        }
+        return null;
+    }
+
     private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
         // check for user specified next focus
         View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
@@ -238,6 +256,13 @@
             View currentCluster,
             List<View> clusters,
             @View.FocusDirection int direction) {
+        try {
+            // Note: This sort is stable.
+            mUserSpecifiedClusterComparator.setFocusables(clusters);
+            Collections.sort(clusters, mUserSpecifiedClusterComparator);
+        } finally {
+            mUserSpecifiedClusterComparator.recycle();
+        }
         final int count = clusters.size();
 
         switch (direction) {
@@ -802,6 +827,15 @@
         private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
         private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
         private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
+        private final NextIdGetter mNextIdGetter;
+
+        public interface NextIdGetter {
+            int get(View view);
+        }
+
+        UserSpecifiedFocusComparator(NextIdGetter nextIdGetter) {
+            mNextIdGetter = nextIdGetter;
+        }
 
         public void recycle() {
             mFocusables.clear();
@@ -810,14 +844,14 @@
             mOriginalOrdinal.clear();
         }
 
-        public void setFocusables(ArrayList<View> focusables) {
+        public void setFocusables(List<View> focusables) {
             for (int i = focusables.size() - 1; i >= 0; i--) {
                 final View view = focusables.get(i);
                 final int id = view.getId();
                 if (isValidId(id)) {
                     mFocusables.put(id, view);
                 }
-                final int nextId = view.getNextFocusForwardId();
+                final int nextId = mNextIdGetter.get(view);
                 if (isValidId(nextId)) {
                     mIsConnectedTo.put(nextId, true);
                 }
@@ -825,7 +859,7 @@
 
             for (int i = focusables.size() - 1; i >= 0; i--) {
                 final View view = focusables.get(i);
-                final int nextId = view.getNextFocusForwardId();
+                final int nextId = mNextIdGetter.get(view);
                 if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
                     setHeadOfChain(view);
                 }
@@ -838,7 +872,7 @@
 
         private void setHeadOfChain(View head) {
             for (View view = head; view != null;
-                    view = mFocusables.get(view.getNextFocusForwardId())) {
+                    view = mFocusables.get(mNextIdGetter.get(view))) {
                 final View otherHead = mHeadsOfChains.get(view);
                 if (otherHead != null) {
                     if (otherHead == head) {
@@ -866,7 +900,7 @@
                     return -1; // first is the head, it should be first
                 } else if (second == firstHead) {
                     return 1; // second is the head, it should be first
-                } else if (isValidId(first.getNextFocusForwardId())) {
+                } else if (isValidId(mNextIdGetter.get(first))) {
                     return -1; // first is not the end of the chain
                 } else {
                     return 1; // first is end of chain
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b12a767..4ffcd95 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -707,13 +707,16 @@
  * @attr ref android.R.styleable#View_isScrollContainer
  * @attr ref android.R.styleable#View_focusable
  * @attr ref android.R.styleable#View_focusableInTouchMode
+ * @attr ref android.R.styleable#View_focusedByDefault
  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
  * @attr ref android.R.styleable#View_keepScreenOn
+ * @attr ref android.R.styleable#View_keyboardNavigationCluster
  * @attr ref android.R.styleable#View_layerType
  * @attr ref android.R.styleable#View_layoutDirection
  * @attr ref android.R.styleable#View_longClickable
  * @attr ref android.R.styleable#View_minHeight
  * @attr ref android.R.styleable#View_minWidth
+ * @attr ref android.R.styleable#View_nextClusterForward
  * @attr ref android.R.styleable#View_nextFocusDown
  * @attr ref android.R.styleable#View_nextFocusLeft
  * @attr ref android.R.styleable#View_nextFocusRight
@@ -4076,7 +4079,9 @@
     int mNextFocusForwardId = View.NO_ID;
 
     /**
-     * User-specified next keyboard navigation cluster.
+     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
+     *
+     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
      */
     int mNextClusterForwardId = View.NO_ID;
 
@@ -9968,6 +9973,29 @@
         return null;
     }
 
+    /**
+     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
+     * use the root to look up the view.
+     *
+     * @param root the root view of the hierarchy containing this view
+     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
+     * @return the user-specified next cluster, or {@code null} if there is none
+     */
+    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
+        switch (direction) {
+            case FOCUS_FORWARD:
+                if (mNextClusterForwardId == View.NO_ID) return null;
+                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
+            case FOCUS_BACKWARD: {
+                if (mID == View.NO_ID) return null;
+                final int id = mID;
+                return root.findViewByPredicateInsideOut(this,
+                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
+            }
+        }
+        return null;
+    }
+
     private View findViewInsideOutShouldExist(View root, int id) {
         if (mMatchIdPredicate == null) {
             mMatchIdPredicate = new MatchIdPredicate();
@@ -20780,11 +20808,18 @@
     }
 
     /**
-     * Look for a child view with the given id.  If this view has the given
-     * id, return this view.
+     * Finds the first descendant view with the given ID, the view itself if
+     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
+     * (< 0) or there is no matching view in the hierarchy.
+     * <p>
+     * <strong>Note:</strong> In most cases -- depending on compiler support --
+     * the resulting view is automatically cast to the target class type. If
+     * the target class type is unconstrained, an explicit cast may be
+     * necessary.
      *
-     * @param id The id to search for.
-     * @return The view that has the given id in the hierarchy or null
+     * @param id the ID to search for
+     * @return a view with given ID if found, or {@code null} otherwise
+     * @see View#findViewById(int)
      */
     @Nullable
     public final <T extends View> T findViewById(@IdRes int id) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c250226..9e1ceee 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1258,15 +1258,18 @@
             return;
         }
 
-        final int count = mChildrenCount;
-        final View[] children = mChildren;
-
-        for (int i = 0; i < count; i++) {
-            final View child = children[i];
+        int count = 0;
+        final View[] visibleChildren = new View[mChildrenCount];
+        for (int i = 0; i < mChildrenCount; ++i) {
+            final View child = mChildren[i];
             if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
-                child.addKeyboardNavigationClusters(views, direction);
+                visibleChildren[count++] = child;
             }
         }
+        Arrays.sort(visibleChildren, 0, count, FocusFinder.getFocusComparator(this, false));
+        for (int i = 0; i < count; ++i) {
+            visibleChildren[i].addKeyboardNavigationClusters(views, direction);
+        }
     }
 
     /**
@@ -7344,6 +7347,7 @@
 
     /** @hide */
     protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
+        requestLayout();
     }
 
     /** @hide */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2e201bf..58ef0af 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4660,6 +4660,7 @@
             if (cluster != null && cluster.isRootNamespace()) {
                 // the default cluster. Try to find a non-clustered view to focus.
                 if (cluster.restoreFocusNotInCluster()) {
+                    playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
                     return true;
                 }
                 // otherwise skip to next actual cluster
@@ -4667,6 +4668,7 @@
             }
 
             if (cluster != null && cluster.restoreFocusInCluster(realDirection)) {
+                playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
                 return true;
             }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0053caa..6dd8ecf 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1308,15 +1308,22 @@
     }
 
     /**
-     * Finds a view that was identified by the id attribute from the XML that
-     * was processed in {@link android.app.Activity#onCreate}.  This will
-     * implicitly call {@link #getDecorView} for you, with all of the
-     * associated side-effects.
+     * Finds a view that was identified by the {@code android:id} XML attribute
+     * that was processed in {@link android.app.Activity#onCreate}. This will
+     * implicitly call {@link #getDecorView} with all of the associated
+     * side-effects.
+     * <p>
+     * <strong>Note:</strong> In most cases -- depending on compiler support --
+     * the resulting view is automatically cast to the target class type. If
+     * the target class type is unconstrained, an explicit cast may be
+     * necessary.
      *
-     * @return The view if found or null otherwise.
+     * @param id the ID to search for
+     * @return a view with given ID if found, or {@code null} otherwise
+     * @see View#findViewById(int)
      */
     @Nullable
-    public View findViewById(@IdRes int id) {
+    public <T extends View> T findViewById(@IdRes int id) {
         return getDecorView().findViewById(id);
     }
 
diff --git a/core/java/android/view/autofill/AutoFillId.java b/core/java/android/view/autofill/AutoFillId.java
deleted file mode 100644
index 081fb02..0000000
--- a/core/java/android/view/autofill/AutoFillId.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2016 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.view.autofill;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
-@Deprecated
-public final class AutoFillId implements Parcelable {
-
-    private final AutofillId mRealId;
-
-    /** @hide */
-    public AutoFillId(AutofillId daRealId) {
-        this.mRealId = daRealId;
-    }
-
-    @Override
-    public int hashCode() {
-        return mRealId.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        final AutoFillId other = (AutoFillId) obj;
-        return mRealId.equals(other.mRealId);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeParcelable(mRealId, 0);
-    }
-
-    private AutoFillId(Parcel parcel) {
-        mRealId = parcel.readParcelable(null);
-    }
-
-    /** @hide */
-    public AutofillId getDaRealId() {
-        return mRealId;
-    }
-
-    /** @hide */
-    public static AutoFillId forDaRealId(AutofillId id) {
-        return id == null ? null : new AutoFillId(id);
-    }
-
-    public static final Parcelable.Creator<AutoFillId> CREATOR =
-            new Parcelable.Creator<AutoFillId>() {
-        @Override
-        public AutoFillId createFromParcel(Parcel source) {
-            return new AutoFillId(source);
-        }
-
-        @Override
-        public AutoFillId[] newArray(int size) {
-            return new AutoFillId[size];
-        }
-    };
-}
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
deleted file mode 100644
index c508ba4..0000000
--- a/core/java/android/view/autofill/AutoFillType.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2016 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.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * Defines the type of a object that can be used to autofill a {@link View} so the
- * {@link android.service.autofill.AutofillService} can use the proper {@link AutofillValue} to
- * fill it.
- *
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use getAutoFilltype
- */
-@Deprecated
-public final class AutoFillType implements Parcelable {
-
-    // Cached instance for types that don't have subtype; it uses the "lazy initialization holder
-    // class idiom" (Effective Java, Item 71) to avoid memory utilization when autofill is not
-    // enabled.
-    private static class DefaultTypesHolder {
-        static final AutoFillType TEXT = new AutoFillType(TYPE_TEXT);
-        static final AutoFillType TOGGLE = new AutoFillType(TYPE_TOGGLE);
-        static final AutoFillType LIST = new AutoFillType(TYPE_LIST);
-        static final AutoFillType DATE = new AutoFillType(TYPE_DATE);
-    }
-
-    private static final int TYPE_TEXT = 1;
-    private static final int TYPE_TOGGLE = 2;
-    private static final int TYPE_LIST = 3;
-    private static final int TYPE_DATE = 4;
-
-    private final int mType;
-
-    private AutoFillType(int type) {
-        mType = type;
-    }
-
-    /**
-     * Checks if this is a type for a text field, which is filled by a {@link CharSequence}.
-     */
-    public boolean isText() {
-        return mType == TYPE_TEXT;
-    }
-
-    /**
-     * Checks if this is a a type for a togglable field, which is filled by a {@code boolean}.
-     */
-    public boolean isToggle() {
-        return mType == TYPE_TOGGLE;
-    }
-
-    /**
-     * Checks if this is a type for a selection list field, which is filled by a {@code integer}
-     * representing the element index inside the list (starting at {@code 0}.
-      */
-    public boolean isList() {
-        return mType == TYPE_LIST;
-    }
-
-    /**
-     * Checks if this is a type for a date and time, which is represented by a long representing
-     * the number of milliseconds since the standard base time known as "the epoch", namely
-     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
-     */
-    public boolean isDate() {
-        return mType == TYPE_DATE;
-    }
-
-    /////////////////////////////////////
-    //  Object "contract" methods. //
-    /////////////////////////////////////
-
-    @Override
-    public String toString() {
-        if (!DEBUG) return super.toString();
-
-        return "AutoFillType [type=" + mType + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + mType;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        final AutoFillType other = (AutoFillType) obj;
-        if (mType != other.mType) return false;
-        return true;
-    }
-
-    /////////////////////////////////////
-    //  Parcelable "contract" methods. //
-    /////////////////////////////////////
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeInt(mType);
-    }
-
-    private AutoFillType(Parcel parcel) {
-        mType = parcel.readInt();
-    }
-
-    public static final Parcelable.Creator<AutoFillType> CREATOR =
-            new Parcelable.Creator<AutoFillType>() {
-        @Override
-        public AutoFillType createFromParcel(Parcel source) {
-            return new AutoFillType(source);
-        }
-
-        @Override
-        public AutoFillType[] newArray(int size) {
-            return new AutoFillType[size];
-        }
-    };
-
-    ////////////////////
-    // Factory methods //
-    ////////////////////
-
-    /**
-     * Creates a text field type, which is filled by a {@link CharSequence}.
-     *
-     * <p>See {@link #isText()} for more info.
-     */
-    public static AutoFillType forText() {
-        return DefaultTypesHolder.TEXT;
-    }
-
-    /**
-     * Creates a type that can be toggled which is filled by a {@code boolean}.
-     *
-     * <p>See {@link #isToggle()} for more info.
-     */
-    public static AutoFillType forToggle() {
-        return DefaultTypesHolder.TOGGLE;
-    }
-
-    /**
-     * Creates a selection list, which is filled by a {@code integer} representing the element index
-     * inside the list (starting at {@code 0}.
-     *
-     * <p>See {@link #isList()} for more info.
-     */
-    public static AutoFillType forList() {
-        return DefaultTypesHolder.LIST;
-    }
-
-    /**
-     * Creates a type that represents a date.
-     *
-     * <p>See {@link #isDate()} for more info.
-     */
-    public static AutoFillType forDate() {
-        return DefaultTypesHolder.DATE;
-    }
-}
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
deleted file mode 100644
index 4774d8f..0000000
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-/**
- * @hide
- * @deprecated TODO(b/35956626): remove once clients use AutofillValue
- */
-@Deprecated
-public final class AutoFillValue implements Parcelable {
-    private final AutofillValue mRealValue;
-
-    private AutoFillValue(AutofillValue daRealValue) {
-        this.mRealValue = daRealValue;
-    }
-
-    /**
-     * Gets the value to autofill a text field.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
-     */
-    public CharSequence getTextValue() {
-        return mRealValue.getTextValue();
-    }
-
-    /**
-     * Gets the value to autofill a toggable field.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
-     */
-    public boolean getToggleValue() {
-        return mRealValue.getToggleValue();
-    }
-
-    /**
-     * Gets the value to autofill a selection list field.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
-     */
-    public int getListValue() {
-        return mRealValue.getListValue();
-    }
-
-    /**
-     * Gets the value to autofill a date field.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
-     */
-    public long getDateValue() {
-        return mRealValue.getDateValue();
-    }
-
-    /////////////////////////////////////
-    //  Object "contract" methods. //
-    /////////////////////////////////////
-
-    @Override
-    public int hashCode() {
-        return mRealValue.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        final AutoFillValue other = (AutoFillValue) obj;
-        return mRealValue.equals(other.mRealValue);
-    }
-
-    @Override
-    public String toString() {
-        if (!DEBUG) return super.toString();
-
-        return mRealValue.toString();
-    }
-
-    /////////////////////////////////////
-    //  Parcelable "contract" methods. //
-    /////////////////////////////////////
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeParcelable(mRealValue, 0);
-    }
-
-    private AutoFillValue(Parcel parcel) {
-        mRealValue = parcel.readParcelable(null);
-    }
-
-    public static final Parcelable.Creator<AutoFillValue> CREATOR =
-            new Parcelable.Creator<AutoFillValue>() {
-        @Override
-        public AutoFillValue createFromParcel(Parcel source) {
-            return new AutoFillValue(source);
-        }
-
-        @Override
-        public AutoFillValue[] newArray(int size) {
-            return new AutoFillValue[size];
-        }
-    };
-
-    ////////////////////
-    // Factory methods //
-    ////////////////////
-    /**
-     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a text field.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.
-     */
-    @Nullable
-    public static AutoFillValue forText(@Nullable CharSequence value) {
-        return value == null ? null : new AutoFillValue(AutofillValue.forText(value));
-    }
-
-    /**
-     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a toggable
-     * field.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.
-     */
-    public static AutoFillValue forToggle(boolean value) {
-        return new AutoFillValue(AutofillValue.forToggle(value));
-    }
-
-    /**
-     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a selection
-     * list.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.
-     */
-    public static AutoFillValue forList(int value) {
-        return new AutoFillValue(AutofillValue.forList(value));
-    }
-
-    /**
-     * Creates a new {@link AutoFillValue} to autofill a {@link View} representing a date.
-     *
-     * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.
-     */
-    public static AutoFillValue forDate(long date) {
-        return new AutoFillValue(AutofillValue.forDate(date));
-    }
-
-    /** @hide */
-    public static AutoFillValue forDaRealValue(AutofillValue daRealValue) {
-        return new AutoFillValue(daRealValue);
-    }
-
-    /** @hide */
-    public AutofillValue getDaRealValue() {
-        return mRealValue;
-    }
-}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 636fa7d..61920bd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -411,8 +411,16 @@
     public abstract  boolean getUseWebViewBackgroundForOverscrollBackground();
 
     /**
-     * Sets whether the WebView should save form data. The default is true.
+     * Sets whether the WebView should save form data. In Android O, the
+     * platform has implemented a fully functional Autofill feature to store
+     * form data. Therefore, the Webview form data save feature is disabled.
+     *
+     * Note that the feature will continue to be supported on older versions of
+     * Android as before.
+     *
+     * This function does not have any effect.
      */
+    @Deprecated
     public abstract  void setSaveFormData(boolean save);
 
     /**
@@ -421,6 +429,7 @@
      * @return whether the WebView saves form data
      * @see #setSaveFormData
      */
+    @Deprecated
     public abstract boolean getSaveFormData();
 
     /**
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 87d3c7b..982c57b 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -143,6 +143,7 @@
      * @return whether there is any saved data for web forms
      * @see #clearFormData
      */
+    @Deprecated
     public abstract boolean hasFormData();
 
     /**
@@ -150,5 +151,6 @@
      *
      * @see #hasFormData
      */
+    @Deprecated
     public abstract void clearFormData();
 }
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index da00d9c..0bf2460 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1443,7 +1443,7 @@
 
     @Override
     public void requestChildFocus(View child, View focused) {
-        if (focused.getRevealOnFocusHint()) {
+        if (focused != null && focused.getRevealOnFocusHint()) {
             if (!mIsLayoutDirty) {
                 scrollToChild(focused);
             } else {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 0a9e361..8fc4f50 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1468,7 +1468,7 @@
 
     @Override
     public void requestChildFocus(View child, View focused) {
-        if (focused.getRevealOnFocusHint()) {
+        if (focused != null && focused.getRevealOnFocusHint()) {
             if (!mIsLayoutDirty) {
                 scrollToChild(focused);
             } else {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6f8df36..1b60ebc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -56,6 +56,7 @@
 import android.graphics.RectF;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
+import android.graphics.fonts.FontVariationAxis;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.LocaleList;
@@ -609,7 +610,7 @@
 
     private int mBreakStrategy;
     private int mHyphenationFrequency;
-    private boolean mJustify;
+    private int mJustificationMode;
 
     private int mMaximum = Integer.MAX_VALUE;
     private int mMaxMode = LINES;
@@ -820,7 +821,7 @@
         String fontFeatureSettings = null;
         mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
         mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
-        mJustify = false;
+        mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
 
         final Resources.Theme theme = context.getTheme();
 
@@ -3737,14 +3738,15 @@
     }
 
     /**
-     * Enables or disables full justification. The default value is false. If the last line is too
-     * short for justification, the last line will be displayed with the alignment set by
-     * {@link android.view.View#setTextAlignment}.
+     * Set justification mode. The default value is {@link Layout#JUSTIFICATION_MODE_NONE}. If the
+     * last line is too short for justification, the last line will be displayed with the
+     * alignment set by {@link android.view.View#setTextAlignment}.
      *
-     * @see #getJustify()
+     * @see #getJustificationMode()
      */
-    public void setJustify(boolean justify) {
-        mJustify = justify;
+    @Layout.JustificationMode
+    public void setJustificationMode(@Layout.JustificationMode int justificationMode) {
+        mJustificationMode = justificationMode;
         if (mLayout != null) {
             nullLayouts();
             requestLayout();
@@ -3753,12 +3755,12 @@
     }
 
     /**
-     * @return true if currently paragraph justification is enabled.
+     * @return true if currently paragraph justification mode.
      *
-     * @see #setJustify(boolean)
+     * @see #setJustificationMode(int)
      */
-    public boolean getJustify() {
-        return mJustify;
+    public @Layout.JustificationMode int getJustificationMode() {
+        return mJustificationMode;
     }
 
     /**
@@ -3808,10 +3810,14 @@
      *         TextView. This function also returns true for empty settings string. Otherwise
      *         returns false.
      *
+     * @throws FontVariationAxis.InvalidFormatException
+     *         If given string is not a valid font variation settings format.
+     *
      * @see #getFontVariationSettings()
      * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
      */
-    public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
+    public boolean setFontVariationSettings(@Nullable String fontVariationSettings)
+            throws FontVariationAxis.InvalidFormatException {
         final String existingSettings = mTextPaint.getFontVariationSettings();
         if (fontVariationSettings == existingSettings
                 || (fontVariationSettings != null
@@ -7678,7 +7684,7 @@
                         .setIncludePad(mIncludePad)
                         .setBreakStrategy(mBreakStrategy)
                         .setHyphenationFrequency(mHyphenationFrequency)
-                        .setJustify(mJustify)
+                        .setJustificationMode(mJustificationMode)
                         .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
                 if (shouldEllipsize) {
                     builder.setEllipsize(mEllipsize)
@@ -7720,7 +7726,7 @@
         if (mText instanceof Spannable) {
             result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth,
                     alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad,
-                    mBreakStrategy, mHyphenationFrequency, mJustify,
+                    mBreakStrategy, mHyphenationFrequency, mJustificationMode,
                     getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth);
         } else {
             if (boring == UNKNOWN_BORING) {
@@ -7770,7 +7776,7 @@
                     .setIncludePad(mIncludePad)
                     .setBreakStrategy(mBreakStrategy)
                     .setHyphenationFrequency(mHyphenationFrequency)
-                    .setJustify(mJustify)
+                    .setJustificationMode(mJustificationMode)
                     .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
             if (shouldEllipsize) {
                 builder.setEllipsize(effectiveEllipsize)
@@ -8110,7 +8116,7 @@
                     .setIncludePad(getIncludeFontPadding())
                     .setBreakStrategy(getBreakStrategy())
                     .setHyphenationFrequency(getHyphenationFrequency())
-                    .setJustify(getJustify())
+                    .setJustificationMode(getJustificationMode())
                     .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                     .setTextDirection(getTextDirectionHeuristic());
 
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index f987a9f..caf35b3 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -55,8 +55,8 @@
             in RemoteViews views);
     void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
     void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
-    ParceledListSlice getInstalledProvidersForProfile(int categoryFilter,
-            int profileId);
+    ParceledListSlice getInstalledProvidersForProfile(int categoryFilter, int profileId,
+            String packageName);
     AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
     boolean hasBindAppWidgetPermission(in String packageName, int userId);
     void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 1abb59b..a70209c 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -74,6 +74,7 @@
     private final Rect mOldStableInsets = new Rect();
     private final Rect mSystemInsets = new Rect();
     private final Rect mStableInsets = new Rect();
+    private final Rect mTmpRect = new Rect();
 
     public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
             Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
@@ -370,12 +371,6 @@
         DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
         mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
         final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
-        final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom,
-                systemInsets.bottom);
-        final int rightInset = DecorView.getColorViewRightInset(stableInsets.right,
-                systemInsets.right);
-        final int leftInset = DecorView.getColorViewLeftInset(stableInsets.left,
-                systemInsets.left);
         if (mStatusBarColor != null) {
             mStatusBarColor.setBounds(0, 0, left + width, topInset);
             mStatusBarColor.draw(canvas);
@@ -385,14 +380,8 @@
         // don't want the navigation bar background be moving around when resizing in docked mode.
         // However, we need it for the transitions into/out of docked mode.
         if (mNavigationBarColor != null && fullscreen) {
-            final int size = DecorView.getNavBarSize(bottomInset, rightInset, leftInset);
-            if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
-                mNavigationBarColor.setBounds(width - size, 0, width, height);
-            } else if (DecorView.isNavBarToLeftEdge(bottomInset, leftInset)) {
-                mNavigationBarColor.setBounds(0, 0, size, height);
-            } else {
-                mNavigationBarColor.setBounds(0, height - size, width, height);
-            }
+            DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect);
+            mNavigationBarColor.setBounds(mTmpRect);
             mNavigationBarColor.draw(canvas);
         }
         mSystemBarBackgroundNode.end(canvas);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index a8e16c9..653796d 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -119,6 +119,21 @@
     // The height of a window which has not in DIP.
     private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
 
+    public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
+            new ColorViewAttributes(SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+                    Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
+                    Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+                    com.android.internal.R.id.statusBarBackground,
+                    FLAG_FULLSCREEN);
+
+    public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
+            new ColorViewAttributes(
+                    SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+                    Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
+                    Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+                    com.android.internal.R.id.navigationBarBackground,
+                    0 /* hideWindowFlag */);
+
     // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
     // size calculation takes the shadow size into account. We set the elevation currently
     // to max until the first layout command has been executed.
@@ -162,18 +177,10 @@
     // View added at runtime to draw under the navigation bar area
     private View mNavigationGuard;
 
-    private final ColorViewState mStatusColorViewState = new ColorViewState(
-            SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
-            Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
-            Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
-            com.android.internal.R.id.statusBarBackground,
-            FLAG_FULLSCREEN);
-    private final ColorViewState mNavigationColorViewState = new ColorViewState(
-            SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
-            Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
-            Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
-            com.android.internal.R.id.navigationBarBackground,
-            0 /* hideWindowFlag */);
+    private final ColorViewState mStatusColorViewState =
+            new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
+    private final ColorViewState mNavigationColorViewState =
+            new ColorViewState(NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES);
 
     private final Interpolator mShowInterpolator;
     private final Interpolator mHideInterpolator;
@@ -983,35 +990,50 @@
         return false;
     }
 
-    static int getColorViewTopInset(int stableTop, int systemTop) {
+    public static int getColorViewTopInset(int stableTop, int systemTop) {
         return Math.min(stableTop, systemTop);
     }
 
-    static int getColorViewBottomInset(int stableBottom, int systemBottom) {
+    public static int getColorViewBottomInset(int stableBottom, int systemBottom) {
         return Math.min(stableBottom, systemBottom);
     }
 
-    static int getColorViewRightInset(int stableRight, int systemRight) {
+    public static int getColorViewRightInset(int stableRight, int systemRight) {
         return Math.min(stableRight, systemRight);
     }
 
-    static int getColorViewLeftInset(int stableLeft, int systemLeft) {
+    public static int getColorViewLeftInset(int stableLeft, int systemLeft) {
         return Math.min(stableLeft, systemLeft);
     }
 
-    static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
+    public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
         return bottomInset == 0 && rightInset > 0;
     }
 
-    static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
+    public static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
         return bottomInset == 0 && leftInset > 0;
     }
 
-    static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
+    public static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
         return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset
                 : isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
     }
 
+    public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
+            Rect contentInsets, Rect outRect) {
+        final int bottomInset = getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom);
+        final int leftInset = getColorViewLeftInset(stableInsets.left, contentInsets.left);
+        final int rightInset = getColorViewLeftInset(stableInsets.right, contentInsets.right);
+        final int size = getNavBarSize(bottomInset, rightInset, leftInset);
+        if (isNavBarToRightEdge(bottomInset, rightInset)) {
+            outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
+        } else if (isNavBarToLeftEdge(bottomInset, leftInset)) {
+            outRect.set(0, 0, size, canvasHeight);
+        } else {
+            outRect.set(0, canvasHeight - size, canvasWidth, canvasHeight);
+        }
+    }
+
     WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
         WindowManager.LayoutParams attrs = mWindow.getAttributes();
         int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
@@ -1131,9 +1153,14 @@
     }
 
     private int calculateStatusBarColor() {
-        int flags = mWindow.getAttributes().flags;
-        return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
-                : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor
+        return calculateStatusBarColor(mWindow.getAttributes().flags,
+                mSemiTransparentStatusBarColor, mWindow.mStatusBarColor);
+    }
+
+    public static int calculateStatusBarColor(int flags, int semiTransparentStatusBarColor,
+            int statusBarColor) {
+        return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? semiTransparentStatusBarColor
+                : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? statusBarColor
                 : Color.BLACK;
     }
 
@@ -1160,13 +1187,9 @@
     private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
             int size, boolean verticalBar, boolean seascape, int sideMargin,
             boolean animate, boolean force) {
-        state.present = (sysUiVis & state.systemUiHideFlag) == 0
-                && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
-                && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
-                        || force);
-        boolean show = state.present
-                && (color & Color.BLACK) != 0
-                && ((mWindow.getAttributes().flags & state.translucentFlag) == 0  || force);
+        state.present = state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force);
+        boolean show = state.attributes.isVisible(state.present, color,
+                mWindow.getAttributes().flags, force);
         boolean showView = show && !isResizing() && size > 0;
 
         boolean visibilityChanged = false;
@@ -1175,15 +1198,15 @@
         int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size;
         int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT;
         int resolvedGravity = verticalBar
-                ? (seascape ? state.seascapeGravity : state.horizontalGravity)
-                : state.verticalGravity;
+                ? (seascape ? state.attributes.seascapeGravity : state.attributes.horizontalGravity)
+                : state.attributes.verticalGravity;
 
         if (view == null) {
             if (showView) {
                 state.view = view = new View(mContext);
                 view.setBackgroundColor(color);
-                view.setTransitionName(state.transitionName);
-                view.setId(state.id);
+                view.setTransitionName(state.attributes.transitionName);
+                view.setId(state.attributes.id);
                 visibilityChanged = true;
                 view.setVisibility(INVISIBLE);
                 state.targetVisibility = VISIBLE;
@@ -2269,6 +2292,15 @@
         boolean visible;
         int color;
 
+        final ColorViewAttributes attributes;
+
+        ColorViewState(ColorViewAttributes attributes) {
+            this.attributes = attributes;
+        }
+    }
+
+    public static class ColorViewAttributes {
+
         final int id;
         final int systemUiHideFlag;
         final int translucentFlag;
@@ -2278,9 +2310,9 @@
         final String transitionName;
         final int hideWindowFlag;
 
-        ColorViewState(int systemUiHideFlag,
-                int translucentFlag, int verticalGravity, int horizontalGravity,
-                int seascapeGravity, String transitionName, int id, int hideWindowFlag) {
+        private ColorViewAttributes(int systemUiHideFlag, int translucentFlag, int verticalGravity,
+                int horizontalGravity, int seascapeGravity, String transitionName, int id,
+                int hideWindowFlag) {
             this.id = id;
             this.systemUiHideFlag = systemUiHideFlag;
             this.translucentFlag = translucentFlag;
@@ -2290,6 +2322,24 @@
             this.transitionName = transitionName;
             this.hideWindowFlag = hideWindowFlag;
         }
+
+        public boolean isPresent(int sysUiVis, int windowFlags, boolean force) {
+            return (sysUiVis & systemUiHideFlag) == 0
+                    && (windowFlags & hideWindowFlag) == 0
+                    && ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+                    || force);
+        }
+
+        public boolean isVisible(boolean present, int color, int windowFlags, boolean force) {
+            return present
+                    && (color & Color.BLACK) != 0
+                    && ((windowFlags & translucentFlag) == 0  || force);
+        }
+
+        public boolean isVisible(int sysUiVis, int color, int windowFlags, boolean force) {
+            final boolean present = isPresent(sysUiVis, windowFlags, force);
+            return isVisible(present, color, windowFlags, force);
+        }
     }
 
     /**
diff --git a/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java b/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java
new file mode 100644
index 0000000..e40090f
--- /dev/null
+++ b/core/java/com/android/internal/view/SurfaceFlingerVsyncChoreographer.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.view;
+
+import android.os.Handler;
+import android.os.Message;
+import android.view.Choreographer;
+import android.view.Display;
+
+/**
+ * Utility class to schedule things at vsync-sf instead of vsync-app
+ * @hide
+ */
+public class SurfaceFlingerVsyncChoreographer {
+
+    private static final long ONE_MS_IN_NS = 1000000;
+    private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
+
+    private final Handler mHandler;
+    private final Choreographer mChoreographer = Choreographer.getInstance();
+
+    /**
+     * The offset between vsync-app and vsync-surfaceflinger. See
+     * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
+     */
+    private long mSurfaceFlingerOffsetMs;
+
+    public SurfaceFlingerVsyncChoreographer(Handler handler, Display display) {
+        mHandler = handler;
+        mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs(display);
+    }
+
+    public long getSurfaceFlingerOffsetMs() {
+        return mSurfaceFlingerOffsetMs;
+    }
+
+    /**
+     * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
+     * is a couple of milliseconds before vsync-sf, a touch or animation event that causes a surface
+     * flinger transaction are sometimes processed before the vsync-sf tick, and sometimes after,
+     * which leads to jank. Figure out this difference here and then post all the touch/animation
+     * events to start being processed at vsync-sf.
+     *
+     * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
+     */
+    private long calculateAppSurfaceFlingerVsyncOffsetMs(Display display) {
+
+        // Calculate vsync offset from SurfaceFlinger.
+        // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
+        long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
+        long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
+        return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
+    }
+
+    public void scheduleAtSfVsync(Runnable r) {
+        final long delay = calculateDelay();
+        if (delay <= 0) {
+            r.run();
+        } else {
+            mHandler.postDelayed(r, delay);
+        }
+    }
+
+    public void scheduleAtSfVsync(Handler h, Message m) {
+        final long delay = calculateDelay();
+        if (delay <= 0) {
+            h.handleMessage(m);
+        } else {
+            m.setAsynchronous(true);
+            h.sendMessageDelayed(m, delay);
+        }
+    }
+
+    private long calculateDelay() {
+        final long sinceFrameStart = System.nanoTime() - mChoreographer.getLastFrameTimeNanos();
+        return mSurfaceFlingerOffsetMs - sinceFrameStart / 1000000;
+    }
+}
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 4e68602..3010dc1 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -245,8 +245,7 @@
     }
 
     sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset, asset));
-    addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
-    return true;
+    return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
 }
 
 static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp
index 91fec2a..3bcf0c7 100644
--- a/core/jni/android/graphics/FontUtils.cpp
+++ b/core/jni/android/graphics/FontUtils.cpp
@@ -55,7 +55,7 @@
     gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
     gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I");
 
-    jclass axisClass = FindClassOrDie(env, "android/text/FontConfig$Axis");
+    jclass axisClass = FindClassOrDie(env, "android/graphics/fonts/FontVariationAxis");
     gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "mTag", "I");
     gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "mStyleValue", "F");
 }
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index a77ed62..1a35330 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -10,6 +10,14 @@
 
 using namespace android::uirenderer;
 
+/**
+ * By default Skia gradients will interpolate their colors in unpremul space
+ * and then premultiply each of the results. We must set this flag to preserve
+ * backwards compatiblity by premultiplying the colors of the gradient first,
+ * and then interpolating between them.
+ */
+static const uint32_t sGradientShaderFlags = SkGradientShader::kInterpolateColorsInPremul_Flag;
+
 static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
     if (NULL == ptr) {
         doThrowIAE(env);
@@ -89,7 +97,7 @@
 
     SkShader* shader = SkGradientShader::MakeLinear(pts,
             reinterpret_cast<const SkColor*>(colorValues), pos, count,
-            static_cast<SkShader::TileMode>(tileMode), /* flags */ 0, matrix).release();
+            static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, matrix).release();
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
     ThrowIAE_IfNull(env, shader);
@@ -109,7 +117,7 @@
     colors[1] = color1;
 
     SkShader* s = SkGradientShader::MakeLinear(pts, colors, NULL, 2,
-            (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
+            static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, matrix).release();
 
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
@@ -135,7 +143,7 @@
 
     SkShader* shader = SkGradientShader::MakeRadial(center, radius,
             reinterpret_cast<const SkColor*>(colorValues), pos, count,
-            static_cast<SkShader::TileMode>(tileMode), /* flags */ 0, matrix).release();
+            static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, matrix).release();
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues),
                                  JNI_ABORT);
 
@@ -154,7 +162,7 @@
     colors[1] = color1;
 
     SkShader* s = SkGradientShader::MakeRadial(center, radius, colors, NULL, 2,
-            (SkShader::TileMode)tileMode, /* flags */ 0, matrix).release();
+            static_cast<SkShader::TileMode>(tileMode), sGradientShaderFlags, matrix).release();
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
 }
@@ -174,8 +182,8 @@
     #error Need to convert float array to SkScalar array before calling the following function.
 #endif
 
-    SkShader* shader = SkGradientShader::MakeSweep(x, y,
-            reinterpret_cast<const SkColor*>(colors), pos, count, /* flags */ 0, matrix).release();
+    SkShader* shader = SkGradientShader::MakeSweep(x, y, reinterpret_cast<const SkColor*>(colors),
+            pos, count, sGradientShaderFlags, matrix).release();
     env->ReleaseIntArrayElements(jcolors, const_cast<jint*>(colors),
                                  JNI_ABORT);
     ThrowIAE_IfNull(env, shader);
@@ -189,7 +197,7 @@
     colors[0] = color0;
     colors[1] = color1;
     SkShader* s = SkGradientShader::MakeSweep(x, y, colors, NULL, 2,
-            /* flags */ 0, matrix).release();
+            sGradientShaderFlags, matrix).release();
     ThrowIAE_IfNull(env, s);
     return reinterpret_cast<jlong>(s);
 }
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index 4b7e0dd..01fe078 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -167,7 +167,7 @@
 }
 
 static jboolean
-android_hardware_UsbRequest_enqueue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
+android_hardware_UsbRequest_queue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
         jint length)
 {
     struct usb_request* request = get_request_from_object(env, thiz);
@@ -226,8 +226,8 @@
     {"native_init",             "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
                                             (void *)android_hardware_UsbRequest_init},
     {"native_close",            "()V",      (void *)android_hardware_UsbRequest_close},
-    {"native_enqueue",         "(Ljava/nio/ByteBuffer;II)Z",
-                                            (void *)android_hardware_UsbRequest_enqueue},
+    {"native_queue",            "(Ljava/nio/ByteBuffer;II)Z",
+                                            (void *)android_hardware_UsbRequest_queue},
     {"native_queue_array",      "([BIZ)Z",  (void *)android_hardware_UsbRequest_queue_array},
     {"native_dequeue_array",    "([BIZ)I",  (void *)android_hardware_UsbRequest_dequeue_array},
     {"native_queue_direct",     "(Ljava/nio/ByteBuffer;IZ)Z",
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 80f9d57..7121194 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -182,7 +182,7 @@
     err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
     if (err != NO_ERROR) return err;
 
-    sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
+    sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
     uint32_t grallocBufWidth = buf->getWidth();
     uint32_t grallocBufHeight = buf->getHeight();
     uint32_t grallocBufStride = buf->getStride();
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 713287e..5839fd5 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -101,17 +101,7 @@
     return sur;
 }
 
-jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
-        const sp<IGraphicBufferProducer>& bufferProducer) {
-    if (bufferProducer == NULL) {
-        return NULL;
-    }
-
-    sp<Surface> surface(new Surface(bufferProducer, true));
-    if (surface == NULL) {
-        return NULL;
-    }
-
+jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
     jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
             gSurfaceClassInfo.ctor, (jlong)surface.get());
     if (surfaceObj == NULL) {
@@ -126,6 +116,16 @@
     return surfaceObj;
 }
 
+jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
+        const sp<IGraphicBufferProducer>& bufferProducer) {
+    if (bufferProducer == NULL) {
+        return NULL;
+    }
+
+    sp<Surface> surface(new Surface(bufferProducer, true));
+    return android_view_Surface_createFromSurface(env, surface);
+}
+
 int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
 
     switch(f) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0ab27f2..b95258b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -346,6 +346,11 @@
         return false;
     }
 
+    // Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
+    if (mount_mode == MOUNT_EXTERNAL_NONE) {
+        return true;
+    }
+
     if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
             NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
         ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
diff --git a/core/jni/include/android_runtime/android_view_Surface.h b/core/jni/include/android_runtime/android_view_Surface.h
index 3f1bdff..2641ab8 100644
--- a/core/jni/include/android_runtime/android_view_Surface.h
+++ b/core/jni/include/android_runtime/android_view_Surface.h
@@ -69,6 +69,10 @@
 /* Gets the underlying Surface from a Surface Java object. */
 extern sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj);
 
+/* Creates a Surface from an android::Surface. */
+extern jobject android_view_Surface_createFromSurface(JNIEnv* env,
+        const sp<Surface>& surface);
+
 /* Creates a Surface from an IGraphicBufferProducer. */
 extern jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
         const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ffcb8476..7922250 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -528,6 +528,7 @@
     <protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
     <protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
     <protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
+    <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
 
     <protected-broadcast android:name="android.content.pm.action.SESSION_COMMITTED" />
     <protected-broadcast android:name="android.os.action.USER_RESTRICTIONS_CHANGED" />
@@ -3346,7 +3347,8 @@
                 android:documentLaunchMode="never"
                 android:relinquishTaskIdentity="true"
                 android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
-                android:process=":ui">
+                android:process=":ui"
+                android:visibleToInstantApps="true">
             <intent-filter>
                 <action android:name="android.intent.action.CHOOSER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3360,7 +3362,8 @@
                   android:documentLaunchMode="never"
                   android:relinquishTaskIdentity="true"
                   android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
-                  android:process=":ui">
+                  android:process=":ui"
+                  android:visibleToInstantApps="true">
             <intent-filter>
                 <action android:name="android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3421,7 +3424,8 @@
                 android:exported="true"
                 android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/choose_account_label"
-                android:process=":ui">
+                android:process=":ui"
+                android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
@@ -3429,14 +3433,16 @@
                 android:exported="true"
                 android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/choose_account_label"
-                android:process=":ui">
+                android:process=":ui"
+                android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
                 android:excludeFromRecents="true"
                 android:theme="@style/Theme.DeviceDefault.Light.Dialog"
                 android:label="@string/choose_account_label"
-                android:process=":ui">
+                android:process=":ui"
+                android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.accounts.CantAddAccountActivity"
@@ -3450,7 +3456,8 @@
                 android:excludeFromRecents="true"
                 android:exported="true"
                 android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
-                android:process=":ui">
+                android:process=":ui"
+                android:visibleToInstantApps="true">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index a165621..5a2bf4e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -17,27 +17,24 @@
 
 <NotificationHeaderView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@style/Theme.Material.Notification"
     android:id="@+id/notification_header"
     android:orientation="horizontal"
     android:layout_width="wrap_content"
     android:layout_height="@dimen/notification_header_height"
     android:clipChildren="false"
-    android:paddingTop="@dimen/notification_header_padding_top"
-    android:paddingBottom="@dimen/notification_header_padding_bottom"
-    android:layout_marginBottom="5dp"
-    android:paddingStart="@dimen/notification_content_margin_start"
-    android:paddingEnd="16dp">
+    style="?attr/notificationHeaderStyle">
     <com.android.internal.widget.CachingIconView
         android:id="@+id/icon"
-        android:layout_width="@dimen/notification_header_icon_size"
-        android:layout_height="@dimen/notification_header_icon_size"
+        android:layout_width="?attr/notificationHeaderIconSize"
+        android:layout_height="?attr/notificationHeaderIconSize"
         android:layout_marginEnd="3dp"
         />
     <TextView
         android:id="@+id/app_name_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="3dp"
         android:layout_marginEnd="2dp"
         android:singleLine="true"
@@ -46,7 +43,7 @@
         android:id="@+id/header_text_divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:text="@string/notification_header_divider_symbol"
@@ -55,7 +52,7 @@
         android:id="@+id/header_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:visibility="gone"
@@ -64,7 +61,7 @@
         android:id="@+id/time_divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:text="@string/notification_header_divider_symbol"
diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml
index e2c68b5..026bc6e 100644
--- a/core/res/res/layout/notification_template_material_ambient.xml
+++ b/core/res/res/layout/notification_template_material_ambient.xml
@@ -20,8 +20,11 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:tag="ambient"
+    android:paddingStart="@dimen/notification_extra_margin_ambient"
+    android:paddingEnd="@dimen/notification_extra_margin_ambient"
     >
-    <include layout="@layout/notification_template_header" />
+    <include layout="@layout/notification_template_header"
+        android:theme="@style/Theme.Material.Notification.Ambient" />
 
     <LinearLayout
             android:id="@+id/notification_action_list_margin_target"
@@ -52,7 +55,7 @@
                 android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
                 android:textSize="20sp"
-                android:textColor="#e6fafafa"
+                android:textColor="#ffffffff"
             />
             <TextView android:id="@+id/text"
                 android:layout_width="match_parent"
@@ -63,7 +66,7 @@
                 android:gravity="top"
                 android:visibility="gone"
                 android:textSize="16sp"
-                android:textColor="#ccfafafa"
+                android:textColor="#eeffffff"
                 android:layout_marginTop="4dp"
             />
         </LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 554f50c..d26d952 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7739,13 +7739,6 @@
         <attr name="settingsActivity" />
     </declare-styleable>
 
-    <!--  TODO(b/35956626): temporary until clients change to AutofillService -->
-    <declare-styleable name="AutoFillService">
-        <!-- Fully qualified class name of an activity that allows the user to modify
-             the settings for this service. -->
-        <attr name="settingsActivity" />
-    </declare-styleable>
-
     <!-- =============================== -->
     <!-- Contacts meta-data attributes -->
     <!-- =============================== -->
@@ -8566,6 +8559,11 @@
         <!-- @hide From Theme.colorBackground, used for the TaskDescription background
                    color. -->
         <attr name="colorBackground" />
+        <!-- @hide From Theme.statusBarColor, used for the TaskDescription status bar color. -->
+        <attr name="statusBarColor"/>
+        <!-- @hide From Theme.navigationBarColor, used for the TaskDescription navigation bar
+                   color. -->
+        <attr name="navigationBarColor"/>
     </declare-styleable>
 
     <declare-styleable name="Shortcut">
@@ -8630,5 +8628,12 @@
         <attr name="stackFromEnd" format="boolean" />
     </declare-styleable>
 
+    <!-- @hide -->
+    <declare-styleable name="NotificationTheme">
+        <attr name="notificationHeaderStyle" format="reference" />
+        <attr name="notificationHeaderTextAppearance" format="reference" />
+        <attr name="notificationHeaderIconSize" format="dimension" />
+    </declare-styleable>
+
     <attr name="lockPatternStyle" format="reference" />
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 85ecaff..221e308 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2822,4 +2822,11 @@
 
     <!-- Whether the device supports quick settings and its associated APIs -->
     <bool name="config_quickSettingsSupported">true</bool>
+
+    <!-- The component name, flattened to a string, for the default autofill service
+         to  enabled for an user. This service must be trusted, as it can be activated
+         without explicit consent of the user. If no autofill service with the
+          specified name exists on the device, autofill will be disabled by default.
+    -->
+    <string name="config_defaultAutofillService" translatable="false"></string>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 1129647..c5316c6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -165,6 +165,9 @@
     -->
     <dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
 
+    <!-- The additional margin on the sides of the ambient view. -->
+    <dimen name="notification_extra_margin_ambient">16dp</dimen>
+
     <!-- The height of the notification action list -->
     <dimen name="notification_action_list_height">56dp</dimen>
 
@@ -188,6 +191,9 @@
     <!-- size (width and height) of the icon in the notification header -->
     <dimen name="notification_header_icon_size">18dp</dimen>
 
+    <!-- size (width and height) of the icon in the notification header -->
+    <dimen name="notification_header_icon_size_ambient">20dp</dimen>
+
     <!-- Height of a small notification in the status bar -->
     <dimen name="notification_min_height">92dp</dimen>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 831cf89..11286f3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3172,7 +3172,7 @@
     <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
     <!-- Notification title when an application is displaying ui on-top of other apps
          [CHAR LIMIT=30] -->
-    <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps.</string>
+    <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
     <!-- Notification body when an application is displaying ui on-top of other apps
          [CHAR LIMIT=NONE] -->
     <string name="alert_windows_notification_message">If you don’t want <xliff:g id="name" example="Google Maps">%s</xliff:g> to use this feature, tap to open settings and turn it off.</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8f061a3..ec16611 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -488,6 +488,10 @@
 
     <style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />
 
+    <style name="TextAppearance.Material.Notification.Info.Ambient">
+        <item name="textSize">@dimen/notification_text_size</item>
+    </style>
+
     <style name="TextAppearance.Material.Notification.Emphasis">
         <item name="textColor">#66000000</item>
     </style>
@@ -1283,4 +1287,12 @@
 
     <style name="DialogWindowTitle.Material.Light" />
 
+    <style name="Notification.Header" parent="">
+        <item name="paddingTop">@dimen/notification_header_padding_top</item>
+        <item name="paddingBottom">@dimen/notification_header_padding_bottom</item>
+        <item name="layout_marginBottom">5dp</item>
+        <item name="paddingStart">@dimen/notification_content_margin_start</item>
+        <item name="paddingEnd">16dp</item>
+    </style>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ae05a69..c12116a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2944,6 +2944,7 @@
   <java-symbol type="string" name="notification_channel_alerts" />
   <java-symbol type="string" name="notification_channel_retail_mode" />
   <java-symbol type="string" name="notification_channel_usb" />
+  <java-symbol type="string" name="config_defaultAutofillService" />
 
   <!-- ETWS primary messages -->
   <java-symbol type="string" name="etws_primary_default_message_earthquake" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 008c817..9dafa7a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1321,6 +1321,19 @@
         <item name="windowNoTitle">true</item>
     </style>
 
+    <!-- Theme for inflating notifications -->
+    <style name="Theme.Material.Notification" parent="">
+        <item name="notificationHeaderStyle">@style/Notification.Header</item>
+        <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info</item>
+        <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size</item>
+    </style>
+
+    <!-- Theme for inflating ambient notification -->
+    <style name="Theme.Material.Notification.Ambient">
+        <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info.Ambient</item>
+        <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size_ambient</item>
+    </style>
+
     <!-- Default theme for Settings and activities launched from Settings. -->
     <style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar">
         <item name="colorPrimary">@color/primary_material_settings_light</item>
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
index 6c1ce44..22bfea1 100644
--- a/core/res/res/xml/time_zones_by_country.xml
+++ b/core/res/res/xml/time_zones_by_country.xml
@@ -31,11 +31,11 @@
 
     <!-- ANTIGUA AND BARBUDA, -4:00 -->
 
-    <timezone code="ag">America/Port_of_Spain</timezone>
+    <timezone code="ag">America/Antigua</timezone>
 
     <!-- ANGUILLA, -4:00 -->
 
-    <timezone code="ai">America/Port_of_Spain</timezone>
+    <timezone code="ai">America/Anguilla</timezone>
 
     <!-- ALBANIA, 1:00 -->
 
@@ -47,11 +47,11 @@
 
     <!-- ANGOLA, 1:00 -->
 
-    <timezone code="ao">Africa/Lagos</timezone>
+    <timezone code="ao">Africa/Luanda</timezone>
 
     <!-- ANTARCTICA, 12:00 -->
 
-    <timezone code="aq">Pacific/Auckland</timezone>
+    <timezone code="aq">Antarctica/McMurdo</timezone>
 
     <!-- ANTARCTICA, 10:00 -->
 
@@ -144,11 +144,11 @@
 
     <!-- ARUBA, -4:00 -->
 
-    <timezone code="aw">America/Curacao</timezone>
+    <timezone code="aw">America/Aruba</timezone>
 
     <!-- ALAND ISLANDS, 2:00 -->
 
-    <timezone code="ax">Europe/Helsinki</timezone>
+    <timezone code="ax">Europe/Mariehamn</timezone>
 
     <!-- AZERBAIJAN, 4:00 -->
 
@@ -156,7 +156,7 @@
 
     <!-- BOSNIA AND HERZEGOVINA, 1:00 -->
 
-    <timezone code="ba">Europe/Belgrade</timezone>
+    <timezone code="ba">Europe/Sarajevo</timezone>
 
     <!-- BARBADOS, -4:00 -->
 
@@ -172,7 +172,7 @@
 
     <!-- BURKINA FASO, 0:00 -->
 
-    <timezone code="bf">Africa/Abidjan</timezone>
+    <timezone code="bf">Africa/Ouagadougou</timezone>
 
     <!-- BULGARIA, 2:00 -->
 
@@ -180,19 +180,19 @@
 
     <!-- BAHRAIN, 3:00 -->
 
-    <timezone code="bh">Asia/Qatar</timezone>
+    <timezone code="bh">Asia/Bahrain</timezone>
 
     <!-- BURUNDI, 2:00 -->
 
-    <timezone code="bi">Africa/Maputo</timezone>
+    <timezone code="bi">Africa/Bujumbura</timezone>
 
     <!-- BENIN, 1:00 -->
 
-    <timezone code="bj">Africa/Lagos</timezone>
+    <timezone code="bj">Africa/Porto-Novo</timezone>
 
     <!-- Saint Barthélemy, -4:00 -->
 
-    <timezone code="bl">America/Port_of_Spain</timezone>
+    <timezone code="bl">America/St_Barthelemy</timezone>
 
     <!-- BERMUDA, -4:00 -->
 
@@ -208,7 +208,7 @@
 
     <!-- Caribbean Netherlands, -4:00 -->
 
-    <timezone code="bq">America/Curacao</timezone>
+    <timezone code="bq">America/Kralendijk</timezone>
 
     <!-- BRAZIL, -2:00 -->
 
@@ -248,7 +248,7 @@
 
     <!-- BOTSWANA, 2:00 -->
 
-    <timezone code="bw">Africa/Maputo</timezone>
+    <timezone code="bw">Africa/Gaborone</timezone>
 
     <!-- BELARUS, 3:00 -->
 
@@ -310,19 +310,19 @@
 
     <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 2:00 -->
 
-    <timezone code="cd">Africa/Maputo</timezone>
+    <timezone code="cd">Africa/Lubumbashi</timezone>
 
     <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE, 1:00 -->
 
-    <timezone code="cd">Africa/Lagos</timezone>
+    <timezone code="cd">Africa/Kinshasa</timezone>
 
     <!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
 
-    <timezone code="cf">Africa/Lagos</timezone>
+    <timezone code="cf">Africa/Bangui</timezone>
 
     <!-- CONGO, 1:00 -->
 
-    <timezone code="cg">Africa/Lagos</timezone>
+    <timezone code="cg">Africa/Brazzaville</timezone>
 
     <!-- SWITZERLAND, 1:00 -->
 
@@ -350,7 +350,7 @@
 
     <!-- CAMEROON, 1:00 -->
 
-    <timezone code="cm">Africa/Lagos</timezone>
+    <timezone code="cm">Africa/Douala</timezone>
 
     <!-- CHINA, 8:00 -->
 
@@ -388,6 +388,10 @@
 
     <timezone code="cy">Asia/Nicosia</timezone>
 
+    <!-- CYPRUS, 3:00 -->
+
+    <timezone code="cy">Asia/Famagusta</timezone>
+
     <!-- CZECH REPUBLIC, 1:00 -->
 
     <timezone code="cz">Europe/Prague</timezone>
@@ -395,11 +399,11 @@
     <!-- GERMANY, 1:00 -->
 
     <timezone code="de">Europe/Berlin</timezone>
-    <timezone code="de">Europe/Zurich</timezone>
+    <timezone code="de">Europe/Busingen</timezone>
 
     <!-- DJIBOUTI, 3:00 -->
 
-    <timezone code="dj">Africa/Nairobi</timezone>
+    <timezone code="dj">Africa/Djibouti</timezone>
 
     <!-- DENMARK, 1:00 -->
 
@@ -407,7 +411,7 @@
 
     <!-- DOMINICA, -4:00 -->
 
-    <timezone code="dm">America/Port_of_Spain</timezone>
+    <timezone code="dm">America/Dominica</timezone>
 
     <!-- DOMINICAN REPUBLIC, -4:00 -->
 
@@ -439,7 +443,7 @@
 
     <!-- ERITREA, 3:00 -->
 
-    <timezone code="er">Africa/Nairobi</timezone>
+    <timezone code="er">Africa/Asmara</timezone>
 
     <!-- SPAIN, 1:00 -->
 
@@ -452,7 +456,7 @@
 
     <!-- ETHIOPIA, 3:00 -->
 
-    <timezone code="et">Africa/Nairobi</timezone>
+    <timezone code="et">Africa/Addis_Ababa</timezone>
 
     <!-- FINLAND, 2:00 -->
 
@@ -468,7 +472,7 @@
 
     <!-- MICRONESIA, FEDERATED STATES OF, 11:00 -->
 
-    <timezone code="fm">Pacific/Ponape</timezone>
+    <timezone code="fm">Pacific/Pohnpei</timezone>
     <timezone code="fm">Pacific/Kosrae</timezone>
 
     <!-- MICRONESIA, FEDERATED STATES OF, 10:00 -->
@@ -485,7 +489,7 @@
 
     <!-- GABON, 1:00 -->
 
-    <timezone code="ga">Africa/Lagos</timezone>
+    <timezone code="ga">Africa/Libreville</timezone>
 
     <!-- UNITED KINGDOM, 0:00 -->
 
@@ -493,7 +497,7 @@
 
     <!-- GRENADA, -4:00 -->
 
-    <timezone code="gd">America/Port_of_Spain</timezone>
+    <timezone code="gd">America/Grenada</timezone>
 
     <!-- GEORGIA, 4:00 -->
 
@@ -505,7 +509,7 @@
 
     <!-- GUERNSEY, 0:00 -->
 
-    <timezone code="gg">Europe/London</timezone>
+    <timezone code="gg">Europe/Guernsey</timezone>
 
     <!-- GHANA, 0:00 -->
 
@@ -533,19 +537,19 @@
 
     <!-- GAMBIA, 0:00 -->
 
-    <timezone code="gm">Africa/Abidjan</timezone>
+    <timezone code="gm">Africa/Banjul</timezone>
 
     <!-- GUINEA, 0:00 -->
 
-    <timezone code="gn">Africa/Abidjan</timezone>
+    <timezone code="gn">Africa/Conakry</timezone>
 
     <!-- GUADELOUPE, -4:00 -->
 
-    <timezone code="gp">America/Port_of_Spain</timezone>
+    <timezone code="gp">America/Guadeloupe</timezone>
 
     <!-- EQUATORIAL GUINEA, 1:00 -->
 
-    <timezone code="gq">Africa/Lagos</timezone>
+    <timezone code="gq">Africa/Malabo</timezone>
 
     <!-- GREECE, 2:00 -->
 
@@ -581,7 +585,7 @@
 
     <!-- CROATIA, 1:00 -->
 
-    <timezone code="hr">Europe/Belgrade</timezone>
+    <timezone code="hr">Europe/Zagreb</timezone>
 
     <!-- HAITI, -5:00 -->
 
@@ -614,7 +618,7 @@
 
     <!-- ISLE OF MAN, 0:00 -->
 
-    <timezone code="im">Europe/London</timezone>
+    <timezone code="im">Europe/Isle_of_Man</timezone>
 
     <!-- INDIA, 5:30 -->
 
@@ -642,7 +646,7 @@
 
     <!-- JERSEY, 0:00 -->
 
-    <timezone code="je">Europe/London</timezone>
+    <timezone code="je">Europe/Jersey</timezone>
 
     <!-- JAMAICA, -5:00 -->
 
@@ -666,7 +670,7 @@
 
     <!-- CAMBODIA, 7:00 -->
 
-    <timezone code="kh">Asia/Bangkok</timezone>
+    <timezone code="kh">Asia/Phnom_Penh</timezone>
 
     <!-- KIRIBATI, 14:00 -->
 
@@ -682,11 +686,11 @@
 
     <!-- COMOROS, 3:00 -->
 
-    <timezone code="km">Africa/Nairobi</timezone>
+    <timezone code="km">Indian/Comoro</timezone>
 
     <!-- SAINT KITTS AND NEVIS, -4:00 -->
 
-    <timezone code="kn">America/Port_of_Spain</timezone>
+    <timezone code="kn">America/St_Kitts</timezone>
 
     <!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
 
@@ -698,11 +702,11 @@
 
     <!-- KUWAIT, 3:00 -->
 
-    <timezone code="kw">Asia/Riyadh</timezone>
+    <timezone code="kw">Asia/Kuwait</timezone>
 
     <!-- CAYMAN ISLANDS, -5:00 -->
 
-    <timezone code="ky">America/Panama</timezone>
+    <timezone code="ky">America/Cayman</timezone>
 
     <!-- KAZAKHSTAN, 6:00 -->
 
@@ -714,10 +718,11 @@
     <timezone code="kz">Asia/Aqtau</timezone>
     <timezone code="kz">Asia/Oral</timezone>
     <timezone code="kz">Asia/Aqtobe</timezone>
+    <timezone code="kz">Asia/Atyrau</timezone>
 
     <!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
 
-    <timezone code="la">Asia/Bangkok</timezone>
+    <timezone code="la">Asia/Vientiane</timezone>
 
     <!-- LEBANON, 2:00 -->
 
@@ -725,11 +730,11 @@
 
     <!-- SAINT LUCIA, -4:00 -->
 
-    <timezone code="lc">America/Port_of_Spain</timezone>
+    <timezone code="lc">America/St_Lucia</timezone>
 
     <!-- LIECHTENSTEIN, 1:00 -->
 
-    <timezone code="li">Europe/Zurich</timezone>
+    <timezone code="li">Europe/Vaduz</timezone>
 
     <!-- SRI LANKA, 5:30 -->
 
@@ -741,7 +746,7 @@
 
     <!-- LESOTHO, 2:00 -->
 
-    <timezone code="ls">Africa/Johannesburg</timezone>
+    <timezone code="ls">Africa/Maseru</timezone>
 
     <!-- LITHUANIA, 2:00 -->
 
@@ -773,15 +778,15 @@
 
     <!-- MONTENEGRO, 1:00 -->
 
-    <timezone code="me">Europe/Belgrade</timezone>
+    <timezone code="me">Europe/Podgorica</timezone>
 
     <!-- Collectivity of Saint Martin, -4:00 -->
 
-    <timezone code="mf">America/Port_of_Spain</timezone>
+    <timezone code="mf">America/Marigot</timezone>
 
     <!-- MADAGASCAR, 3:00 -->
 
-    <timezone code="mg">Africa/Nairobi</timezone>
+    <timezone code="mg">Indian/Antananarivo</timezone>
 
     <!-- MARSHALL ISLANDS, 12:00 -->
 
@@ -790,11 +795,11 @@
 
     <!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
 
-    <timezone code="mk">Europe/Belgrade</timezone>
+    <timezone code="mk">Europe/Skopje</timezone>
 
     <!-- MALI, 0:00 -->
 
-    <timezone code="ml">Africa/Abidjan</timezone>
+    <timezone code="ml">Africa/Bamako</timezone>
 
     <!-- MYANMAR, 6:30 -->
 
@@ -815,7 +820,7 @@
 
     <!-- NORTHERN MARIANA ISLANDS, 10:00 -->
 
-    <timezone code="mp">Pacific/Guam</timezone>
+    <timezone code="mp">Pacific/Saipan</timezone>
 
     <!-- MARTINIQUE, -4:00 -->
 
@@ -823,11 +828,11 @@
 
     <!-- MAURITANIA, 0:00 -->
 
-    <timezone code="mr">Africa/Abidjan</timezone>
+    <timezone code="mr">Africa/Nouakchott</timezone>
 
     <!-- MONTSERRAT, -4:00 -->
 
-    <timezone code="ms">America/Port_of_Spain</timezone>
+    <timezone code="ms">America/Montserrat</timezone>
 
     <!-- MALTA, 1:00 -->
 
@@ -843,7 +848,7 @@
 
     <!-- MALAWI, 2:00 -->
 
-    <timezone code="mw">Africa/Maputo</timezone>
+    <timezone code="mw">Africa/Blantyre</timezone>
 
     <!-- MEXICO, -6:00 -->
 
@@ -887,7 +892,7 @@
 
     <!-- NIGER, 1:00 -->
 
-    <timezone code="ne">Africa/Lagos</timezone>
+    <timezone code="ne">Africa/Niamey</timezone>
 
     <!-- NORFOLK ISLAND, 11:30 -->
 
@@ -911,7 +916,7 @@
 
     <!-- NEPAL, 5:45 -->
 
-    <timezone code="np">Asia/Katmandu</timezone>
+    <timezone code="np">Asia/Kathmandu</timezone>
 
     <!-- NAURU, 12:00 -->
 
@@ -931,7 +936,7 @@
 
     <!-- OMAN, 4:00 -->
 
-    <timezone code="om">Asia/Dubai</timezone>
+    <timezone code="om">Asia/Muscat</timezone>
 
     <!-- PANAMA, -5:00 -->
 
@@ -1070,6 +1075,7 @@
     <timezone code="ru">Europe/Samara</timezone>
     <timezone code="ru">Europe/Astrakhan</timezone>
     <timezone code="ru">Europe/Ulyanovsk</timezone>
+    <timezone code="ru">Europe/Saratov</timezone>
 
     <!-- RUSSIAN FEDERATION, 3:00 -->
 
@@ -1084,7 +1090,7 @@
 
     <!-- RWANDA, 2:00 -->
 
-    <timezone code="rw">Africa/Maputo</timezone>
+    <timezone code="rw">Africa/Kigali</timezone>
 
     <!-- SAUDI ARABIA, 3:00 -->
 
@@ -1112,35 +1118,35 @@
 
     <!-- SAINT HELENA, 0:00 -->
 
-    <timezone code="sh">Africa/Abidjan</timezone>
+    <timezone code="sh">Atlantic/St_Helena</timezone>
 
     <!-- SLOVENIA, 1:00 -->
 
-    <timezone code="si">Europe/Belgrade</timezone>
+    <timezone code="si">Europe/Ljubljana</timezone>
 
     <!-- SVALBARD AND JAN MAYEN, 1:00 -->
 
-    <timezone code="sj">Europe/Oslo</timezone>
+    <timezone code="sj">Arctic/Longyearbyen</timezone>
 
     <!-- SLOVAKIA, 1:00 -->
 
-    <timezone code="sk">Europe/Prague</timezone>
+    <timezone code="sk">Europe/Bratislava</timezone>
 
     <!-- SIERRA LEONE, 0:00 -->
 
-    <timezone code="sl">Africa/Abidjan</timezone>
+    <timezone code="sl">Africa/Freetown</timezone>
 
     <!-- SAN MARINO, 1:00 -->
 
-    <timezone code="sm">Europe/Rome</timezone>
+    <timezone code="sm">Europe/San_Marino</timezone>
 
     <!-- SENEGAL, 0:00 -->
 
-    <timezone code="sn">Africa/Abidjan</timezone>
+    <timezone code="sn">Africa/Dakar</timezone>
 
     <!-- SOMALIA, 3:00 -->
 
-    <timezone code="so">Africa/Nairobi</timezone>
+    <timezone code="so">Africa/Mogadishu</timezone>
 
     <!-- SURINAME, -3:00 -->
 
@@ -1148,11 +1154,11 @@
 
     <!-- South Sudan, 3:00 -->
 
-    <timezone code="ss">Africa/Khartoum</timezone>
+    <timezone code="ss">Africa/Juba</timezone>
 
     <!-- SAO TOME AND PRINCIPE, 0:00 -->
 
-    <timezone code="st">Africa/Abidjan</timezone>
+    <timezone code="st">Africa/Sao_Tome</timezone>
 
     <!-- EL SALVADOR, -6:00 -->
 
@@ -1160,7 +1166,7 @@
 
     <!-- Sint Maarten, -4:00 -->
 
-    <timezone code="sx">America/Curacao</timezone>
+    <timezone code="sx">America/Lower_Princes</timezone>
 
     <!-- SYRIAN ARAB REPUBLIC, 2:00 -->
 
@@ -1168,7 +1174,7 @@
 
     <!-- SWAZILAND, 2:00 -->
 
-    <timezone code="sz">Africa/Johannesburg</timezone>
+    <timezone code="sz">Africa/Mbabane</timezone>
 
     <!-- TURKS AND CAICOS ISLANDS, -4:00 -->
 
@@ -1182,13 +1188,9 @@
 
     <timezone code="tf">Indian/Kerguelen</timezone>
 
-    <!-- FRENCH SOUTHERN TERRITORIES, 4:00 -->
-
-    <timezone code="tf">Indian/Reunion</timezone>
-
     <!-- TOGO, 0:00 -->
 
-    <timezone code="tg">Africa/Abidjan</timezone>
+    <timezone code="tg">Africa/Lome</timezone>
 
     <!-- THAILAND, 7:00 -->
 
@@ -1236,7 +1238,7 @@
 
     <!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
 
-    <timezone code="tz">Africa/Nairobi</timezone>
+    <timezone code="tz">Africa/Dar_es_Salaam</timezone>
 
     <!-- UKRAINE, 2:00 -->
 
@@ -1246,19 +1248,15 @@
 
     <!-- UGANDA, 3:00 -->
 
-    <timezone code="ug">Africa/Nairobi</timezone>
+    <timezone code="ug">Africa/Kampala</timezone>
 
     <!-- UNITED STATES MINOR OUTLYING ISLANDS, 12:00 -->
 
     <timezone code="um">Pacific/Wake</timezone>
 
-    <!-- UNITED STATES MINOR OUTLYING ISLANDS, -10:00 -->
-
-    <timezone code="um">Pacific/Honolulu</timezone>
-
     <!-- UNITED STATES MINOR OUTLYING ISLANDS, -11:00 -->
 
-    <timezone code="um">Pacific/Pago_Pago</timezone>
+    <timezone code="um">Pacific/Midway</timezone>
 
     <!-- UNITED STATES, -5:00 -->
 
@@ -1318,11 +1316,11 @@
 
     <!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
 
-    <timezone code="va">Europe/Rome</timezone>
+    <timezone code="va">Europe/Vatican</timezone>
 
     <!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
 
-    <timezone code="vc">America/Port_of_Spain</timezone>
+    <timezone code="vc">America/St_Vincent</timezone>
 
     <!-- VENEZUELA, -4:00 -->
 
@@ -1330,16 +1328,15 @@
 
     <!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
 
-    <timezone code="vg">America/Port_of_Spain</timezone>
+    <timezone code="vg">America/Tortola</timezone>
 
     <!-- VIRGIN ISLANDS, U.S., -4:00 -->
 
-    <timezone code="vi">America/Port_of_Spain</timezone>
+    <timezone code="vi">America/St_Thomas</timezone>
 
     <!-- VIET NAM, 7:00 -->
 
     <timezone code="vn">Asia/Ho_Chi_Minh</timezone>
-    <timezone code="vn">Asia/Bangkok</timezone>
 
     <!-- VANUATU, 11:00 -->
 
@@ -1355,11 +1352,11 @@
 
     <!-- YEMEN, 3:00 -->
 
-    <timezone code="ye">Asia/Riyadh</timezone>
+    <timezone code="ye">Asia/Aden</timezone>
 
     <!-- MAYOTTE, 3:00 -->
 
-    <timezone code="yt">Africa/Nairobi</timezone>
+    <timezone code="yt">Indian/Mayotte</timezone>
 
     <!-- SOUTH AFRICA, 2:00 -->
 
@@ -1367,9 +1364,9 @@
 
     <!-- ZAMBIA, 2:00 -->
 
-    <timezone code="zm">Africa/Maputo</timezone>
+    <timezone code="zm">Africa/Lusaka</timezone>
 
     <!-- ZIMBABWE, 2:00 -->
 
-    <timezone code="zw">Africa/Maputo</timezone>
+    <timezone code="zw">Africa/Harare</timezone>
 </timezones>
diff --git a/core/tests/coretests/src/android/graphics/VariationParserTest.java b/core/tests/coretests/src/android/graphics/VariationParserTest.java
deleted file mode 100644
index fdabb13..0000000
--- a/core/tests/coretests/src/android/graphics/VariationParserTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2016 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.graphics;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.FontConfig;
-
-import junit.framework.TestCase;
-
-import java.util.List;
-
-
-public class VariationParserTest extends TestCase {
-
-    @SmallTest
-    public void testParseFontVariationSetting() {
-        int tag = FontListParser.makeTag("wdth");
-        List<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings("'wdth' 1");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(1.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("\"wdth\" 100");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(100.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("   'wdth' 100");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(100.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(0.5f, axes.get(0).getStyleValue());
-
-        tag = FontListParser.makeTag("AX  ");
-        axes = FontListParser.parseFontVariationSettings("'AX  ' 1");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(1.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("'AX  '\t1");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(1.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("'AX  '\n1");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(1.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("'AX  '\r1");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(1.0f, axes.get(0).getStyleValue());
-
-        axes = FontListParser.parseFontVariationSettings("'AX  '\r\t\n 1");
-        assertEquals(tag, axes.get(0).getTag());
-        assertEquals(1.0f, axes.get(0).getStyleValue());
-
-        // Test for invalid input
-        axes = FontListParser.parseFontVariationSettings("");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("invalid_form");
-        assertEquals(0, axes.size());
-
-        // Test with invalid tag
-        axes = FontListParser.parseFontVariationSettings("'' 1");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'invalid' 1");
-        assertEquals(0, axes.size());
-
-        // Test with invalid styleValue
-        axes = FontListParser.parseFontVariationSettings("'wdth' ");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'wdth' x");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'wdth' \t");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'wdth' \n\r");
-        assertEquals(0, axes.size());
-    }
-
-    @SmallTest
-    public void testParseFontVariationStyleSettings() {
-        List<FontConfig.Axis> axes =
-                FontListParser.parseFontVariationSettings("'wdth' 10,'AX  '\r1");
-        int tag1 = FontListParser.makeTag("wdth");
-        int tag2 = FontListParser.makeTag("AX  ");
-        assertEquals(tag1, axes.get(0).getTag());
-        assertEquals(10.0f, axes.get(0).getStyleValue());
-        assertEquals(tag2, axes.get(1).getTag());
-        assertEquals(1.0f, axes.get(1).getStyleValue());
-
-        // Test only spacers are allowed before tag
-        axes = FontListParser.parseFontVariationSettings("     'wdth' 10,ab'wdth' 1");
-        tag1 = FontListParser.makeTag("wdth");
-        assertEquals(tag1, axes.get(0).getTag());
-        assertEquals(10.0f, axes.get(0).getStyleValue());
-        assertEquals(1, axes.size());
-    }
-
-    @SmallTest
-    public void testInvalidTagCharacters() {
-        List<FontConfig.Axis> axes =
-                FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
-        assertEquals(0, axes.size());
-    }
-
-    @SmallTest
-    public void testMakeTag() {
-      assertEquals(0x77647468, FontListParser.makeTag("wdth"));
-      assertEquals(0x41582020, FontListParser.makeTag("AX  "));
-      assertEquals(0x20202020, FontListParser.makeTag("    "));
-    }
-}
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index 6820e92..1dd3ef6 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -94,7 +94,8 @@
         FontResult fontResult = resultList.get(0);
         assertEquals(TestFontsProvider.TTC_INDEX, fontResult.getTtcIndex());
         assertEquals(TestFontsProvider.VARIATION_SETTINGS, fontResult.getFontVariationSettings());
-        assertEquals(TestFontsProvider.STYLE, fontResult.getStyle());
+        assertEquals(TestFontsProvider.NORMAL_WEIGHT, fontResult.getWeight());
+        assertEquals(TestFontsProvider.ITALIC, fontResult.getItalic());
         assertNotNull(fontResult.getFileDescriptor());
     }
 
@@ -115,7 +116,8 @@
         FontResult fontResult = resultList.get(0);
         assertEquals(0, fontResult.getTtcIndex());
         assertNull(fontResult.getFontVariationSettings());
-        assertEquals(Typeface.NORMAL, fontResult.getStyle());
+        assertEquals(400, fontResult.getWeight());
+        assertFalse(fontResult.getItalic());
         assertNotNull(fontResult.getFileDescriptor());
     }
 
@@ -146,10 +148,10 @@
     public void testGetFontFromProvider_resultFontNotFoundSecondRow() {
         MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
                 FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
-                FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
-                FontsContract.Columns.RESULT_CODE_OK});
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+                FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+                FontsContract.Columns.RESULT_CODE });
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0,
                 FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
         mProvider.setCustomCursor(cursor);
         mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
@@ -160,13 +162,12 @@
     public void testGetFontFromProvider_resultFontNotFoundOtherRow() {
         MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
                 FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
-                FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
-                FontsContract.Columns.RESULT_CODE_OK});
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
+                FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+                FontsContract.Columns.RESULT_CODE });
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0,
                 FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
-                FontsContract.Columns.RESULT_CODE_OK});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
         mProvider.setCustomCursor(cursor);
         mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
 
@@ -176,10 +177,10 @@
     public void testGetFontFromProvider_resultCodeIsNegativeNumber() {
         MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
                 FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
-                FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL,
-                FontsContract.Columns.RESULT_CODE_OK});
-        cursor.addRow(new Object[] { 1, 0, null, Typeface.NORMAL, -5});
+                FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+                FontsContract.Columns.RESULT_CODE });
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, -5});
         mProvider.setCustomCursor(cursor);
         mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
 
diff --git a/core/tests/coretests/src/android/provider/TestFontsProvider.java b/core/tests/coretests/src/android/provider/TestFontsProvider.java
index 13f5318..46906df 100644
--- a/core/tests/coretests/src/android/provider/TestFontsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestFontsProvider.java
@@ -37,7 +37,8 @@
     static final String AUTHORITY = "android.provider.TestFontsProvider";
     static final int TTC_INDEX = 2;
     static final String VARIATION_SETTINGS = "'wdth' 1";
-    static final int STYLE = Typeface.BOLD;
+    static final int NORMAL_WEIGHT = 400;
+    static final boolean ITALIC = false;
 
     private ParcelFileDescriptor mPfd;
     private boolean mReturnAllFields = true;
@@ -81,8 +82,9 @@
         if (mReturnAllFields) {
             cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
                     FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
-                    FontsContract.Columns.STYLE, FontsContract.Columns.RESULT_CODE });
-            cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, STYLE, mResultCode });
+                    FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
+                    FontsContract.Columns.RESULT_CODE });
+            cursor.addRow(new Object[] { 1, TTC_INDEX, VARIATION_SETTINGS, 400, 0, mResultCode });
         } else {
             cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID });
             cursor.addRow(new Object[] { 1 });
diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java
new file mode 100644
index 0000000..bcc47e1
--- /dev/null
+++ b/core/tests/coretests/src/android/text/VariationParserTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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.text;
+
+import android.graphics.fonts.FontVariationAxis;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+public class VariationParserTest extends TestCase {
+    private static final String[] INVALID_STYLE_VALUES = {
+        "", "x", "\t", "\n"
+    };
+
+    @SmallTest
+    public void testFromFontVariationSetting_InvalidStyleValue() {
+        // Test with invalid styleValue
+        for (String invalidStyle : INVALID_STYLE_VALUES) {
+            try {
+                FontVariationAxis.fromFontVariationSettings("'wdth' " + invalidStyle);
+                fail();
+            } catch (FontVariationAxis.InvalidFormatException e) {
+                // pass
+            }
+        }
+        for (String invalidStyle : INVALID_STYLE_VALUES) {
+            try {
+                FontVariationAxis.fromFontVariationSettings("'wght' 1, 'wdth' " + invalidStyle);
+                fail();
+            } catch (FontVariationAxis.InvalidFormatException e) {
+                // pass
+            }
+        }
+    }
+
+    @SmallTest
+    public void testOpenTypeTagValue() throws FontVariationAxis.InvalidFormatException {
+      assertEquals(0x77647468, (new FontVariationAxis("wdth", 0).getOpenTypeTagValue()));
+      assertEquals(0x41582020, (new FontVariationAxis("AX  ", 0).getOpenTypeTagValue()));
+      assertEquals(0x20202020, (new FontVariationAxis("    ", 0).getOpenTypeTagValue()));
+    }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 344f3c8..86ab3dc 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -181,6 +181,9 @@
     <allow-in-power-save package="com.android.cellbroadcastreceiver" />
     <allow-in-power-save package="com.android.shell" />
 
+    <!-- STOPSHIP(b/36856786): Revert this once it is fixed properly -->
+    <allow-in-power-save package="com.google.android.apps.enterprise.dmagent" />
+
     <!-- These are the packages that are white-listed to be able to run as system user -->
     <system-user-whitelisted-app package="com.android.settings" />
 
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 76c29a9..3dab1f7 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -3,15 +3,10 @@
     WARNING: Parsing of this file by third-party apps is not supported. The
     file, and the font files it refers to, will be renamed and/or moved out
     from their respective location in the next Android release, and/or the
-    format or syntax of the file may change significantly. You must not
-    parse this file for information about system fonts. Instead, you must
-    call android.text.FontManager#getSystemFonts(). For example, it can be
-    called as context.getSystemService(FontManager.class).getSystemFonts().
-    Note that the returned FontConfig includes data on all the defined font
-    families and all the details about weight, style, etc. It also provides
-    an open file descriptor to each font file. Note that callers of the API
-    should ensure they close the given file descriptors once they are done
-    using them.
+    format or syntax of the file may change significantly. If you parse this
+    file for information about system fonts, do it at your own risk. Your
+    application will almost certainly break with the next major Android
+    release.
 
     In this file, all fonts without names are added to the default list.
     Fonts are chosen based on a match: full BCP-47 language tag including
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 6214ba6..4b1b0c6 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.content.res.AssetManager;
+import android.graphics.fonts.FontVariationAxis;
 import android.text.FontConfig;
 import android.util.Log;
 import dalvik.annotation.optimization.CriticalNative;
@@ -81,7 +82,7 @@
         }
     }
 
-    public boolean addFont(String path, int ttcIndex, FontConfig.Axis[] axes, int weight,
+    public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
             int italic) {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("Unable to call addFont after freezing.");
@@ -91,8 +92,8 @@
             long fontSize = fileChannel.size();
             ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
             if (axes != null) {
-                for (FontConfig.Axis axis : axes) {
-                    nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
+                for (FontVariationAxis axis : axes) {
+                    nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
                 }
             }
             return nAddFont(mBuilderPtr, fontBuffer, ttcIndex, weight, italic);
@@ -102,14 +103,14 @@
         }
     }
 
-    public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontConfig.Axis[] axes,
+    public boolean addFontFromBuffer(ByteBuffer font, int ttcIndex, FontVariationAxis[] axes,
             int weight, int italic) {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
         }
         if (axes != null) {
-            for (FontConfig.Axis axis : axes) {
-                nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
+            for (FontVariationAxis axis : axes) {
+                nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
             }
         }
         return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, weight, italic);
@@ -129,13 +130,13 @@
      */
     public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie,
             boolean isAsset, int ttcIndex, int weight, int isItalic,
-            FontConfig.Axis[] axes) {
+            FontVariationAxis[] axes) {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
         }
         if (axes != null) {
-            for (FontConfig.Axis axis : axes) {
-                nAddAxisValue(mBuilderPtr, axis.getTag(), axis.getStyleValue());
+            for (FontVariationAxis axis : axes) {
+                nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
             }
         }
         return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index ff9f11d..1a4f225 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -17,6 +17,7 @@
 package android.graphics;
 
 import android.text.FontConfig;
+import android.graphics.fonts.FontVariationAxis;
 import android.util.Xml;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -50,72 +51,6 @@
         }
     }
 
-    // Note that a well-formed variation contains a four-character tag and a float as styleValue,
-    // with spacers in between. The tag is enclosd either by double quotes or single quotes.
-    @VisibleForTesting
-    public static ArrayList<FontConfig.Axis> parseFontVariationSettings(@Nullable String settings) {
-        ArrayList<FontConfig.Axis> axisList = new ArrayList<>();
-        if (settings == null) {
-            return axisList;
-        }
-        String[] settingList = settings.split(",");
-        settingLoop:
-        for (String setting : settingList) {
-            int pos = 0;
-            while (pos < setting.length()) {
-                char c = setting.charAt(pos);
-                if (c == '\'' || c == '"') {
-                    break;
-                } else if (!isSpacer(c)) {
-                    continue settingLoop;  // Only spacers are allowed before tag appeared.
-                }
-                pos++;
-            }
-            if (pos + 7 > setting.length()) {
-                continue;  // 7 is the minimum length of tag-style value pair text.
-            }
-            if (setting.charAt(pos) != setting.charAt(pos + 5)) {
-                continue;  // Tag should be wrapped with double or single quote.
-            }
-            String tagString = setting.substring(pos + 1, pos + 5);
-            if (!TAG_PATTERN.matcher(tagString).matches()) {
-                continue;  // Skip incorrect format tag.
-            }
-            pos += 6;
-            while (pos < setting.length()) {
-                if (!isSpacer(setting.charAt(pos++))) {
-                    break;  // Skip spacers between the tag and the styleValue.
-                }
-            }
-            // Skip invalid styleValue
-            float styleValue;
-            String valueString = setting.substring(pos - 1);
-            if (!STYLE_VALUE_PATTERN.matcher(valueString).matches()) {
-                continue;  // Skip incorrect format styleValue.
-            }
-            try {
-                styleValue = Float.parseFloat(valueString);
-            } catch (NumberFormatException e) {
-                continue;  // ignoreing invalid number format
-            }
-            int tag = makeTag(tagString);
-            axisList.add(new FontConfig.Axis(tag, styleValue));
-        }
-        return axisList;
-    }
-
-    public static int makeTag(String tagString) {
-        char c1 = tagString.charAt(0);
-        char c2 = tagString.charAt(1);
-        char c3 = tagString.charAt(2);
-        char c4 = tagString.charAt(3);
-        return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
-    }
-
-    private static boolean isSpacer(char c) {
-        return c == ' ' || c == '\r' || c == '\t' || c == '\n';
-    }
-
     private static FontConfig readFamilies(XmlPullParser parser)
             throws XmlPullParserException, IOException {
         List<FontConfig.Family> families = new ArrayList<>();
@@ -172,7 +107,7 @@
             throws XmlPullParserException, IOException {
         String indexStr = parser.getAttributeValue(null, "index");
         int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
-        List<FontConfig.Axis> axes = new ArrayList<FontConfig.Axis>();
+        List<FontVariationAxis> axes = new ArrayList<FontVariationAxis>();
         String weightStr = parser.getAttributeValue(null, "weight");
         int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
         boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));
@@ -191,47 +126,20 @@
         }
         String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
         return new FontConfig.Font(sanitizedName, index,
-                axes.toArray(new FontConfig.Axis[axes.size()]), weight, isItalic);
+                axes.toArray(new FontVariationAxis[axes.size()]), weight, isItalic);
     }
 
-    /** The 'tag' attribute value is read as four character values between U+0020 and U+007E
-     *  inclusive.
-     */
-    private static final Pattern TAG_PATTERN = Pattern.compile("[\\x20-\\x7E]{4}");
-
-    public static boolean isValidTag(String tagString) {
-        if (tagString == null || tagString.length() != 4) {
-            return false;
-        }
-        return TAG_PATTERN.matcher(tagString).matches();
-    }
-
-    /** The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
-     *  '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
-     */
-    private static final Pattern STYLE_VALUE_PATTERN =
-            Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))");
-
-    private static FontConfig.Axis readAxis(XmlPullParser parser)
+    private static FontVariationAxis readAxis(XmlPullParser parser)
             throws XmlPullParserException, IOException {
-        int tag = 0;
         String tagStr = parser.getAttributeValue(null, "tag");
-        if (isValidTag(tagStr)) {
-            tag = makeTag(tagStr);
-        } else {
-            throw new XmlPullParserException("Invalid tag attribute value.", parser, null);
-        }
-
-        float styleValue = 0;
         String styleValueStr = parser.getAttributeValue(null, "stylevalue");
-        if (styleValueStr != null && STYLE_VALUE_PATTERN.matcher(styleValueStr).matches()) {
-            styleValue = Float.parseFloat(styleValueStr);
-        } else {
-            throw new XmlPullParserException("Invalid styleValue attribute value.", parser, null);
-        }
-
         skip(parser);  // axis tag is empty, ignore any contents and consume end tag
-        return new FontConfig.Axis(tag, styleValue);
+        try {
+            return new FontVariationAxis(tagStr, Float.parseFloat(styleValueStr));
+        } catch (FontVariationAxis.InvalidFormatException e) {
+            // Treat as system failure since system preinstalled font setting has invalid format.
+            throw new RuntimeException(e);
+        }
     }
 
     private static FontConfig.Alias readAlias(XmlPullParser parser)
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index c4f7dc3..828729a 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Size;
 import android.graphics.FontListParser;
+import android.graphics.fonts.FontVariationAxis;
 import android.os.LocaleList;
 import android.text.FontConfig;
 import android.text.GraphicsOperations;
@@ -1551,8 +1552,11 @@
      * @return true if the given settings is effective to at least one font file underlying this
      *         typeface. This function also returns true for empty settings string. Otherwise
      *         returns false
+     * @throws FontVariationAxis.InvalidFormatException
+     *         If given string is not a valid font variation settings format.
      */
-    public boolean setFontVariationSettings(String settings) {
+    public boolean setFontVariationSettings(String settings)
+            throws FontVariationAxis.InvalidFormatException {
         settings = TextUtils.nullIfEmpty(settings);
         if (settings == mFontVariationSettings
                 || (settings != null && settings.equals(mFontVariationSettings))) {
@@ -1566,11 +1570,10 @@
             return true;
         }
 
-        final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(settings);
-        final ArrayList<FontConfig.Axis> filteredAxes = new ArrayList<FontConfig.Axis>();
-        for (int i = 0; i < axes.size(); ++i) {
-            final FontConfig.Axis axis = axes.get(i);
-            if (mTypeface.isSupportedAxes(axis.getTag())) {
+        FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings(settings);
+        final ArrayList<FontVariationAxis> filteredAxes = new ArrayList<FontVariationAxis>();
+        for (final FontVariationAxis axis : axes) {
+            if (mTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) {
                 filteredAxes.add(axis);
             }
         }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 8c3a2e8..5afe5e9 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -32,6 +32,7 @@
 import android.graphics.FontListParser;
 import android.graphics.fonts.FontRequest;
 import android.graphics.fonts.FontResult;
+import android.graphics.fonts.FontVariationAxis;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
@@ -356,13 +357,17 @@
                 long fontSize = fileChannel.size();
                 ByteBuffer fontBuffer = fileChannel.map(
                         FileChannel.MapMode.READ_ONLY, 0, fontSize);
-                int style = result.getStyle();
-                int weight = (style & BOLD) != 0 ? 700 : 400;
-                final ArrayList<FontConfig.Axis> axes = FontListParser.parseFontVariationSettings(
-                        result.getFontVariationSettings());
+                int weight = result.getWeight();
+                int italic = result.getItalic() ? Builder.ITALIC : Builder.NORMAL;
+                FontVariationAxis[] axes = null;
+                try {
+                    axes = FontVariationAxis.fromFontVariationSettings(
+                            result.getFontVariationSettings());
+                } catch (FontVariationAxis.InvalidFormatException e) {
+                    // TODO: Nice to pass FontVariationAxis[] directly instead of string.
+                }
                 if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(),
-                                axes.toArray(new FontConfig.Axis[axes.size()]), weight,
-                                (style & ITALIC) == 0 ? Builder.NORMAL : Builder.ITALIC)) {
+                        axes, weight, italic)) {
                     Log.e(TAG, "Error creating font " + request.getQuery());
                     callback.onTypefaceRequestFailed(
                             FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
@@ -514,7 +519,7 @@
         public static final int ITALIC = 1;
 
         private int mTtcIndex;
-        private FontConfig.Axis[] mAxes;
+        private FontVariationAxis[] mAxes;
 
         private AssetManager mAssetManager;
         private String mPath;
@@ -682,15 +687,16 @@
          * Sets a font variation settings.
          *
          * @param variationSettings See {@link android.widget.TextView#setFontVariationSettings}.
+         * @throws FontVariationAxis.InvalidFormatException If given string is not a valid font
+         *                                                  variation settings format.
          */
-        public Builder setFontVariationSettings(@Nullable String variationSettings) {
+        public Builder setFontVariationSettings(@Nullable String variationSettings)
+                throws FontVariationAxis.InvalidFormatException {
             checkNotRecycled();
             if (mAxes != null) {
                 throw new IllegalStateException("Font variation settings are already set.");
             }
-            final List<FontConfig.Axis> axesList = FontListParser.parseFontVariationSettings(
-                    variationSettings);
-            mAxes = axesList.toArray(new FontConfig.Axis[axesList.size()]);
+            mAxes = FontVariationAxis.fromFontVariationSettings(variationSettings);
             return this;
         }
 
@@ -699,7 +705,7 @@
          *
          * @param axes An array of font variation axis tag-value pairs.
          */
-        public Builder setFontVariationSettings(@Nullable FontConfig.Axis[] axes) {
+        public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
             checkNotRecycled();
             if (mAxes != null) {
                 throw new IllegalStateException("Font variation settings are already set.");
@@ -718,7 +724,7 @@
          * @return Unique id for a given AssetManager and asset path.
          */
         private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
-                @Nullable FontConfig.Axis[] axes) {
+                @Nullable FontVariationAxis[] axes) {
             final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
             final StringBuilder builder = new StringBuilder();
             final int size = pkgs.size();
@@ -731,8 +737,8 @@
             builder.append(Integer.toString(ttcIndex));
             builder.append("-");
             if (axes != null) {
-                for (FontConfig.Axis axis : axes) {
-                    builder.append(Integer.toHexString(axis.getTag()));
+                for (FontVariationAxis axis : axes) {
+                    builder.append(axis.getTag());
                     builder.append("-");
                     builder.append(Float.toString(axis.getStyleValue()));
                 }
@@ -865,7 +871,7 @@
 
     /** @hide */
     public static Typeface createFromTypefaceWithVariation(Typeface family,
-            List<FontConfig.Axis> axes) {
+            List<FontVariationAxis> axes) {
         final long ni = family == null ? 0 : family.native_instance;
         return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
     }
@@ -1162,9 +1168,9 @@
     }
 
     private static native long nativeCreateFromTypeface(long native_instance, int style);
-    // TODO: clean up: change List<FontConfig.Axis> to FontConfig.Axis[]
+    // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
     private static native long nativeCreateFromTypefaceWithVariation(
-            long native_instance, List<FontConfig.Axis> axes);
+            long native_instance, List<FontVariationAxis> axes);
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
     private static native void nativeUnref(long native_instance);
     private static native int  nativeGetStyle(long native_instance);
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 04864bdc..a491d7e 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -88,9 +88,7 @@
     }
 
     @Override
-    public
-    @Config
-    int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations()
                 | mDrawableContainerState.getChangingConfigurations();
     }
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 322e55b..b159f0f 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -32,6 +32,7 @@
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.LayoutDirection;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
 
@@ -66,6 +67,8 @@
  * @attr ref android.R.styleable#LayerDrawableItem_id
 */
 public class LayerDrawable extends Drawable implements Drawable.Callback {
+    private static final String LOG_TAG = "LayerDrawable";
+
     /**
      * Padding mode used to nest each layer inside the padding of the previous
      * layer.
@@ -89,6 +92,7 @@
      */
     public static final int INSET_UNDEFINED = Integer.MIN_VALUE;
 
+    @NonNull
     LayerState mLayerState;
 
     private int[] mPaddingL;
@@ -170,13 +174,9 @@
             throws XmlPullParserException, IOException {
         super.inflate(r, parser, attrs, theme);
 
-        final LayerState state = mLayerState;
-        if (state == null) {
-            return;
-        }
-
         // The density may have changed since the last update. This will
         // apply scaling to any existing constant state properties.
+        final LayerState state = mLayerState;
         final int density = Drawable.resolveDensity(r, 0);
         state.setDensity(density);
 
@@ -202,10 +202,6 @@
         super.applyTheme(t);
 
         final LayerState state = mLayerState;
-        if (state == null) {
-            return;
-        }
-
         final int density = Drawable.resolveDensity(t.getResources(), 0);
         state.setDensity(density);
 
@@ -403,7 +399,7 @@
 
     @Override
     public boolean canApplyTheme() {
-        return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme();
+        return mLayerState.canApplyTheme() || super.canApplyTheme();
     }
 
     /**
@@ -1841,15 +1837,24 @@
                 final ConstantState cs = dr.getConstantState();
                 if (cs == null) {
                     clone = dr;
+                    if (dr.getCallback() != null) {
+                        // This drawable already has an owner.
+                        Log.w(LOG_TAG, "Invalid drawable added to LayerDrawable! Drawable already "
+                                + "belongs to another owner but does not expose a constant state.",
+                                new RuntimeException());
+                    }
                 } else if (res != null) {
                     clone = cs.newDrawable(res);
                 } else {
                     clone = cs.newDrawable();
                 }
-                clone.setCallback(owner);
                 clone.setLayoutDirection(dr.getLayoutDirection());
                 clone.setBounds(dr.getBounds());
                 clone.setLevel(dr.getLevel());
+
+                // Set the callback last to prevent invalidation from
+                // propagating before the constant state has been set.
+                clone.setCallback(owner);
             } else {
                 clone = null;
             }
diff --git a/graphics/java/android/graphics/fonts/FontResult.java b/graphics/java/android/graphics/fonts/FontResult.java
index 3ef99fd..20e736e 100644
--- a/graphics/java/android/graphics/fonts/FontResult.java
+++ b/graphics/java/android/graphics/fonts/FontResult.java
@@ -35,7 +35,8 @@
     private final ParcelFileDescriptor mFileDescriptor;
     private final int mTtcIndex;
     private final String mFontVariationSettings;
-    private final int mStyle;
+    private final int mWeight;
+    private final boolean mItalic;
 
     /**
      * Creates a FontResult with all the information needed about a provided font.
@@ -45,16 +46,16 @@
      *                       will fail to load in the client application.
      * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
      * @param fontVariationSettings If providing a variation font, the settings for it. May be null.
-     * @param style One of {@link android.graphics.Typeface#NORMAL},
-     *              {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC}
-     *              or {@link android.graphics.Typeface#BOLD_ITALIC}
+     * @param weight An integer that indicates the font weight.
+     * @param italic A boolean that indicates the font is italic style or not.
      */
     public FontResult(@NonNull ParcelFileDescriptor fileDescriptor, int ttcIndex,
-            @Nullable String fontVariationSettings, int style) {
+            @Nullable String fontVariationSettings, int weight, boolean italic) {
         mFileDescriptor = Preconditions.checkNotNull(fileDescriptor);
         mTtcIndex = ttcIndex;
         mFontVariationSettings = fontVariationSettings;
-        mStyle = style;
+        mWeight = weight;
+        mItalic = italic;
     }
 
     public ParcelFileDescriptor getFileDescriptor() {
@@ -69,8 +70,12 @@
         return mFontVariationSettings;
     }
 
-    public int getStyle() {
-        return mStyle;
+    public int getWeight() {
+        return mWeight;
+    }
+
+    public boolean getItalic() {
+        return mItalic;
     }
 
     @Override
@@ -83,14 +88,16 @@
         dest.writeParcelable(mFileDescriptor, flags);
         dest.writeInt(mTtcIndex);
         dest.writeString(mFontVariationSettings);
-        dest.writeInt(mStyle);
+        dest.writeInt(mWeight);
+        dest.writeBoolean(mItalic);
     }
 
     private FontResult(Parcel in) {
         mFileDescriptor = in.readParcelable(null);
         mTtcIndex = in.readInt();
         mFontVariationSettings = in.readString();
-        mStyle = in.readInt();
+        mWeight = in.readInt();
+        mItalic = in.readBoolean();
     }
 
     public static final Parcelable.Creator<FontResult> CREATOR =
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
new file mode 100644
index 0000000..91ec0e8
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+/**
+ * Class that holds information about single font variation axis.
+ */
+public final class FontVariationAxis implements Parcelable {
+    private final int mTag;
+    private final String mTagString;
+    private final float mStyleValue;
+
+    /**
+     * Construct FontVariationAxis.
+     *
+     * The axis tag must contain four ASCII characters. Tag string that are longer or shorter than
+     * four characters, or contains characters outside of U+0020..U+007E are invalid.
+     *
+     * @throws {@link InvalidFormatException} If given tag string is invalid.
+     */
+    public FontVariationAxis(@NonNull String tagString, float styleValue)
+            throws InvalidFormatException {
+        if (!isValidTag(tagString)) {
+            throw new InvalidFormatException("Invalid tag pattern: " + tagString);
+        }
+        mTag = makeTag(tagString);
+        mTagString = tagString;
+        mStyleValue = styleValue;
+    }
+
+    /**
+     * Returns the OpenType style tag value.
+     * @hide
+     */
+    public int getOpenTypeTagValue() {
+        return mTag;
+    }
+
+    /**
+     * Returns the variable font axis tag associated to this axis.
+     */
+    public String getTag() {
+        return mTagString;
+    }
+
+    /**
+     * Returns the style value associated to the given axis for this font.
+     */
+    public float getStyleValue() {
+        return mStyleValue;
+    }
+
+    /**
+     * @hide
+     */
+    public FontVariationAxis(Parcel in) {
+        mTag = in.readInt();
+        mTagString = in.readString();
+        mStyleValue = in.readFloat();
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flag) {
+        out.writeInt(mTag);
+        out.writeString(mTagString);
+        out.writeFloat(mStyleValue);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<FontVariationAxis> CREATOR = new Creator<FontVariationAxis>() {
+        @Override
+        public FontVariationAxis createFromParcel(Parcel in) {
+            return new FontVariationAxis(in);
+        }
+
+        @Override
+        public FontVariationAxis[] newArray(int size) {
+            return new FontVariationAxis[size];
+        }
+    };
+
+    /**
+     * Returns a valid font variation setting string for this object.
+     */
+    @Override
+    public @NonNull String toString() {
+        return "'" + mTagString + "' " + Float.toString(mStyleValue);
+    }
+
+    /**
+     * The 'tag' attribute value is read as four character values between U+0020 and U+007E
+     * inclusive.
+     */
+    private static final Pattern TAG_PATTERN = Pattern.compile("[\u0020-\u007E]{4}");
+
+    /**
+     * Returns true if 'tagString' is valid for font variation axis tag.
+     */
+    private static boolean isValidTag(String tagString) {
+        return tagString != null && TAG_PATTERN.matcher(tagString).matches();
+    }
+
+    /**
+     * The 'styleValue' attribute has an optional leading '-', followed by '<digits>',
+     * '<digits>.<digits>', or '.<digits>' where '<digits>' is one or more of [0-9].
+     */
+    private static final Pattern STYLE_VALUE_PATTERN =
+            Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))");
+
+    private static boolean isValidValueFormat(String valueString) {
+        return valueString != null && STYLE_VALUE_PATTERN.matcher(valueString).matches();
+    }
+
+    /** @hide */
+    public static int makeTag(String tagString) {
+        final char c1 = tagString.charAt(0);
+        final char c2 = tagString.charAt(1);
+        final char c3 = tagString.charAt(2);
+        final char c4 = tagString.charAt(3);
+        return (c1 << 24) | (c2 << 16) | (c3 << 8) | c4;
+    }
+
+    /**
+     * An exception indicates that the format of font variation settings is invalid.
+     */
+    public static class InvalidFormatException extends Exception {
+        public InvalidFormatException(String message) {
+            super(message);
+        }
+    };
+
+    /**
+     * Construct FontVariationAxis array from font variation settings.
+     *
+     * The settings string is constructed from multiple pairs of axis tag and style values. The axis
+     * tag must contain four ASCII characters and must be wrapped with single quotes (U+0027) or
+     * double quotes (U+0022). Axis strings that are longer or shorter than four characters, or
+     * contain characters outside of U+0020..U+007E are invalid. If a specified axis name is not
+     * defined in the font, the settings will be ignored.
+     *
+     * <pre>
+     *   FontVariationAxis.fromFontVariationSettings("'wdth' 1.0");
+     *   FontVariationAxis.fromFontVariationSettings("'AX  ' 1.0, 'FB  ' 2.0");
+     * </pre>
+     *
+     * @param settings font variation settings.
+     * @return FontVariationAxis[] the array of parsed font variation axis. {@code null} if settings
+     *                             has no font variation settings.
+     * @throws InvalidFormatException If given string is not a valid font variation settings format.
+     */
+    public static @Nullable FontVariationAxis[] fromFontVariationSettings(@Nullable String settings)
+            throws InvalidFormatException {
+        if (settings == null || settings.isEmpty()) {
+            return null;
+        }
+        final ArrayList<FontVariationAxis> axisList = new ArrayList<>();
+        final int length = settings.length();
+        for (int i = 0; i < length; i++) {
+            final char c = settings.charAt(i);
+            if (Character.isWhitespace(c)) {
+                continue;
+            }
+            if (!(c == '\'' || c == '"') || length < i + 6 || settings.charAt(i + 5) != c) {
+                throw new InvalidFormatException(
+                        "Tag should be wrapped with double or single quote: " + settings);
+            }
+            final String tagString = settings.substring(i + 1, i + 5);
+
+            i += 6;  // Move to end of tag.
+            int endOfValueString = settings.indexOf(',', i);
+            if (endOfValueString == -1) {
+                endOfValueString = length;
+            }
+            final float value;
+            try {
+                // Float.parseFloat ignores leading/trailing whitespaces.
+                value = Float.parseFloat(settings.substring(i, endOfValueString));
+            } catch (NumberFormatException e) {
+                throw new InvalidFormatException("Failed to parse float string: " + e.getMessage());
+            }
+            axisList.add(new FontVariationAxis(tagString, value));
+            i = endOfValueString;
+        }
+        if (axisList.isEmpty()) {
+            return null;
+        }
+        return axisList.toArray(new FontVariationAxis[0]);
+    }
+
+    /**
+     * Stringify the array of FontVariationAxis.
+     *
+     * @param axes an array of FontVariationAxis.
+     * @return String a valid font variation settings string.
+     */
+    public static @NonNull String toFontVariationSettings(@Nullable FontVariationAxis[] axes) {
+        if (axes == null || axes.length == 0) {
+            return "";
+        }
+        return TextUtils.join(",", axes);
+    }
+}
+
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index dceb285..d4d0c99 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -189,9 +189,9 @@
         float amount, uint8_t*& dst) const {
     float oppAmount = 1.0f - amount;
     float a = start.a * oppAmount + end.a * amount;
-    *dst++ = uint8_t(a * OECF(start.r * oppAmount + end.r * amount) * 255.0f);
-    *dst++ = uint8_t(a * OECF(start.g * oppAmount + end.g * amount) * 255.0f);
-    *dst++ = uint8_t(a * OECF(start.b * oppAmount + end.b * amount) * 255.0f);
+    *dst++ = uint8_t(OECF(start.r * oppAmount + end.r * amount) * 255.0f);
+    *dst++ = uint8_t(OECF(start.g * oppAmount + end.g * amount) * 255.0f);
+    *dst++ = uint8_t(OECF(start.b * oppAmount + end.b * amount) * 255.0f);
     *dst++ = uint8_t(a * 255.0f);
 }
 
@@ -202,13 +202,13 @@
     float* d = (float*) dst;
 #ifdef ANDROID_ENABLE_LINEAR_BLENDING
     // We want to stay linear
-    *d++ = a * (start.r * oppAmount + end.r * amount);
-    *d++ = a * (start.g * oppAmount + end.g * amount);
-    *d++ = a * (start.b * oppAmount + end.b * amount);
+    *d++ = (start.r * oppAmount + end.r * amount);
+    *d++ = (start.g * oppAmount + end.g * amount);
+    *d++ = (start.b * oppAmount + end.b * amount);
 #else
-    *d++ = a * OECF(start.r * oppAmount + end.r * amount);
-    *d++ = a * OECF(start.g * oppAmount + end.g * amount);
-    *d++ = a * OECF(start.b * oppAmount + end.b * amount);
+    *d++ = OECF(start.r * oppAmount + end.r * amount);
+    *d++ = OECF(start.g * oppAmount + end.g * amount);
+    *d++ = OECF(start.b * oppAmount + end.b * amount);
 #endif
     *d++ = a;
     dst += 4 * sizeof(float);
@@ -229,10 +229,10 @@
     ChannelMixer mix = gMixers[mUseFloatTexture];
 
     FloatColor start;
-    start.setUnPreMultiplied(colors[0]);
+    start.set(colors[0]);
 
     FloatColor end;
-    end.setUnPreMultiplied(colors[1]);
+    end.set(colors[1]);
 
     int currentPos = 1;
     float startPos = positions[0];
@@ -247,7 +247,7 @@
 
             currentPos++;
 
-            end.setUnPreMultiplied(colors[currentPos]);
+            end.set(colors[currentPos]);
             distance = positions[currentPos] - startPos;
         }
 
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 1f78e09..d0f0949 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -295,10 +295,6 @@
         vec4 dither(const vec4 color) {
             return color + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
         }
-        vec4 gradientMix(const vec4 a, const vec4 b, float v) {
-            vec4 c = mix(a, b, v);
-            return vec4(c.rgb * c.a, c.a);
-        }
         )__SHADER__",
         // sRGB framebuffer
         R"__SHADER__(
@@ -306,10 +302,6 @@
             vec3 dithered = sqrt(color.rgb) + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0);
             return vec4(dithered * dithered, color.a);
         }
-        vec4 gradientMixMix(const vec4 a, const vec4 b, float v) {
-            vec4 c = mix(a, b, v);
-            return vec4(c.rgb * c.a, c.a);
-        }
         )__SHADER__",
 };
 
@@ -364,19 +356,19 @@
         // Linear
         "    vec4 gradientColor = texture2D(gradientSampler, linear);\n",
 
-        "    vec4 gradientColor = gradientMix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
+        "    vec4 gradientColor = mix(startColor, endColor, clamp(linear, 0.0, 1.0));\n",
 
         // Circular
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(length(circular), 0.5));\n",
 
-        "    vec4 gradientColor = gradientMix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
+        "    vec4 gradientColor = mix(startColor, endColor, clamp(length(circular), 0.0, 1.0));\n",
 
         // Sweep
         "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n",
 
         "    highp float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
-        "    vec4 gradientColor = gradientMix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
+        "    vec4 gradientColor = mix(startColor, endColor, clamp(index - floor(index), 0.0, 1.0));\n"
 };
 const char* gFS_Main_FetchBitmap =
         "    vec4 bitmapColor = colorConvert(texture2D(bitmapSampler, outBitmapTexCoords));\n";
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 8a504d4..5c5378b 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -173,8 +173,8 @@
         outData->gradientSampler = 0;
         outData->gradientTexture = nullptr;
 
-        outData->startColor.setUnPreMultiplied(gradInfo.fColors[0]);
-        outData->endColor.setUnPreMultiplied(gradInfo.fColors[1]);
+        outData->startColor.set(gradInfo.fColors[0]);
+        outData->endColor.set(gradInfo.fColors[1]);
     }
 
     return true;
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index 7f06421..8826cfc 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -27,5 +27,7 @@
     libft2 \
     libminikin \
     libandroidfw \
-    libRScpp \
+    libRScpp
+
+LOCAL_STATIC_LIBRARIES += \
     libplatformprotos
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 2ead5c5..d26eb59 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -162,7 +162,7 @@
     SkAutoCanvasRestore acr(canvas, true);
 
     SkMatrix shadowMatrix;
-    mat4 hwuiMatrix(caster->getRecordedMatrix());
+    mat4 hwuiMatrix;
     // TODO we don't pass the optional boolean to treat it as a 4x4 matrix
     caster->getRenderNode()->applyViewPropertyTransforms(hwuiMatrix);
     hwuiMatrix.copyTo(shadowMatrix);
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 652954b..686d06f 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -941,3 +941,67 @@
     EXPECT_EQ(2, canvas.mDrawCounter);
 }
 
+
+TEST(ReorderBarrierDrawable, testShadowMatrix) {
+    static const int CANVAS_WIDTH = 100;
+    static const int CANVAS_HEIGHT = 100;
+    static const float TRANSLATE_X = 11.0f;
+    static const float TRANSLATE_Y = 22.0f;
+    static const float CASTER_X = 40.0f;
+    static const float CASTER_Y = 40.0f;
+    static const float CASTER_WIDTH = 20.0f;
+    static const float CASTER_HEIGHT = 20.0f;
+
+
+    class ShadowTestCanvas : public SkCanvas {
+    public:
+        ShadowTestCanvas(int width, int height) : SkCanvas(width, height) {}
+        int getIndex() { return mDrawCounter; }
+
+        virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
+            // expect to draw 2 RenderNodeDrawable, 1 StartReorderBarrierDrawable,
+            // 1 EndReorderBarrierDrawable
+            mDrawCounter++;
+            SkCanvas::onDrawDrawable(drawable, matrix);
+        }
+
+        virtual void didTranslate(SkScalar dx, SkScalar dy) override {
+            mDrawCounter++;
+            EXPECT_EQ(dx, TRANSLATE_X);
+            EXPECT_EQ(dy, TRANSLATE_Y);
+        }
+
+        virtual void didConcat(const SkMatrix& matrix) override {
+            // This function is invoked by EndReorderBarrierDrawable::drawShadow to apply shadow
+            // matrix.
+            mDrawCounter++;
+            EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X, CASTER_Y), matrix);
+            EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X+TRANSLATE_X, CASTER_Y+TRANSLATE_Y),
+                    getTotalMatrix());
+        }
+    protected:
+        int mDrawCounter = 0;
+    };
+
+    auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        canvas.translate(TRANSLATE_X, TRANSLATE_Y);
+        canvas.insertReorderBarrier(true);
+
+        auto node = TestUtils::createSkiaNode(CASTER_X, CASTER_Y, CASTER_X + CASTER_WIDTH,
+                CASTER_Y + CASTER_HEIGHT,
+                [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                    props.setElevation(42);
+                    props.mutableOutline().setRoundRect(0, 0, 20, 20, 5, 1);
+                    props.mutableOutline().setShouldClip(true);
+                });
+        canvas.drawRenderNode(node.get());
+        canvas.insertReorderBarrier(false);
+    });
+
+    //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+    ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
+    RenderNodeDrawable drawable(parent.get(), &canvas, false);
+    canvas.drawDrawable(&drawable);
+    EXPECT_EQ(6, canvas.getIndex());
+}
\ No newline at end of file
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c7796cd..4adbf79 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2540,6 +2540,44 @@
 
     /**
      * @hide
+     * Notifies an application with a focus listener of gain or loss of audio focus.
+     * This method can only be used by owners of an {@link AudioPolicy} configured with
+     * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to true.
+     * @param afi the recipient of the focus change, that has previously requested audio focus, and
+     *     that was received by the {@code AudioPolicy} through
+     *     {@link AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(AudioFocusInfo, int)}.
+     * @param focusChange one of focus gain types ({@link #AUDIOFOCUS_GAIN},
+     *     {@link #AUDIOFOCUS_GAIN_TRANSIENT}, {@link #AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK} or
+     *     {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE})
+     *     or one of the focus loss types ({@link AudioManager#AUDIOFOCUS_LOSS},
+     *     {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT},
+     *     or {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}).
+     *     <br>For the focus gain, the change type should be the same as the app requested.
+     * @param ap a valid registered {@link AudioPolicy} configured as a focus policy.
+     * @return {@link #AUDIOFOCUS_REQUEST_GRANTED} if the dispatch was successfully sent, or
+     *     {@link #AUDIOFOCUS_REQUEST_FAILED} if the focus client didn't have a listener, or
+     *     if there was an error sending the request.
+     * @throws NullPointerException if the {@link AudioFocusInfo} or {@link AudioPolicy} are null.
+     */
+    @SystemApi
+    public int dispatchAudioFocusChange(@NonNull AudioFocusInfo afi, int focusChange,
+            @NonNull AudioPolicy ap) {
+        if (afi == null) {
+            throw new NullPointerException("Illegal null AudioFocusInfo");
+        }
+        if (ap == null) {
+            throw new NullPointerException("Illegal null AudioPolicy");
+        }
+        final IAudioService service = getService();
+        try {
+            return service.dispatchFocusChange(afi, focusChange, ap.cb());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
      * Used internally by telephony package to abandon audio focus, typically after a call or
      * when ringing ends and the call is rejected or not answered.
      * Should match one or more calls to {@link #requestAudioFocusForCall(int, int)}.
@@ -2548,7 +2586,7 @@
         final IAudioService service = getService();
         try {
             service.abandonAudioFocus(null, AudioSystem.IN_VOICE_COMM_FOCUS_ID,
-                    null /*AudioAttributes, legacy behavior*/);
+                    null /*AudioAttributes, legacy behavior*/, getContext().getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2579,7 +2617,7 @@
         final IAudioService service = getService();
         try {
             status = service.abandonAudioFocus(mAudioFocusDispatcher,
-                    getIdForAudioFocusListener(l), aa);
+                    getIdForAudioFocusListener(l), aa, getContext().getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2787,7 +2825,7 @@
         final IAudioService service = getService();
         try {
             String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
-                    policy.hasFocusListener());
+                    policy.hasFocusListener(), policy.isFocusPolicy());
             if (regId == null) {
                 return ERROR;
             } else {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5855984..884d41e 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -20,6 +20,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
 import android.media.AudioAttributes;
+import android.media.AudioFocusInfo;
 import android.media.AudioPlaybackConfiguration;
 import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
@@ -122,7 +123,8 @@
             IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
             IAudioPolicyCallback pcb);
 
-    int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa);
+    int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa,
+            in String callingPackageName);
 
     void unregisterAudioFocusClient(String clientId);
 
@@ -164,7 +166,7 @@
     boolean isHdmiSystemAudioSupported();
 
     String registerAudioPolicy(in AudioPolicyConfig policyConfig,
-            in IAudioPolicyCallback pcb, boolean hasFocusListener);
+            in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy);
 
     oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
 
@@ -196,5 +198,8 @@
 
     int getFocusRampTimeMs(in int focusGain, in AudioAttributes attr);
 
+    int dispatchFocusChange(in AudioFocusInfo afi, in int focusChange,
+            in IAudioPolicyCallback pcb);
+
     // WARNING: read warning at top of file, it is recommended to add new methods at the end
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index cdc1d60..4675e32 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -746,14 +746,19 @@
     }
 
     /**
-     * Sets the video encoding profile for recording. Call this method before prepare().
-     * Prepare() may perform additional checks on the parameter to make sure whether the
-     * specified profile and level are applicable, and sometimes the passed profile or
-     * level will be discarded due to codec capablity or to ensure the video recording
-     * can proceed smoothly based on the capabilities of the platform.
-     * @hide
+     * Sets the desired video encoding profile and level for recording. The profile and level
+     * must be valid for the video encoder set by {@link #setVideoEncoder}. This method can
+     * called before or after {@link #setVideoEncoder} but it must be called before {@link #prepare}.
+     * {@code prepare()} may perform additional checks on the parameter to make sure that the specified
+     * profile and level are applicable, and sometimes the passed profile or level will be
+     * discarded due to codec capablity or to ensure the video recording can proceed smoothly
+     * based on the capabilities of the platform. <br>Application can also use the
+     * {@link MediaCodecInfo.CodecCapabilities#profileLevels} to query applicable combination of profile
+     * and level for the corresponding format. Note that the requested profile/level may not be supported by
+     * the codec that is actually being used by this MediaRecorder instance.
      * @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}.
      * @param level declared in {@link MediaCodecInfo.CodecProfileLevel}.
+     * @throws IllegalArgumentException when an invalid profile or level value is used.
      */
     public void setVideoEncodingProfileLevel(int profile, int level) {
         if (profile <= 0)  {
@@ -1281,3 +1286,4 @@
     @Override
     protected void finalize() { native_finalize(); }
 }
+
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 423b467..61d642f 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -68,6 +68,7 @@
     private int mStatus;
     private String mRegistrationId;
     private AudioPolicyStatusListener mStatusListener;
+    private boolean mIsFocusPolicy;
 
     /**
      * The behavior of a policy with regards to audio focus where it relies on the application
@@ -96,12 +97,14 @@
     public AudioPolicyConfig getConfig() { return mConfig; }
     /** @hide */
     public boolean hasFocusListener() { return mFocusListener != null; }
+    /** @hide */
+    public boolean isFocusPolicy() { return mIsFocusPolicy; }
 
     /**
      * The parameter is guaranteed non-null through the Builder
      */
     private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
-            AudioPolicyFocusListener fl, AudioPolicyStatusListener sl) {
+            AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy) {
         mConfig = config;
         mStatus = POLICY_STATUS_UNREGISTERED;
         mContext = context;
@@ -116,10 +119,12 @@
         }
         mFocusListener = fl;
         mStatusListener = sl;
+        mIsFocusPolicy = isFocusPolicy;
     }
 
     /**
-     * Builder class for {@link AudioPolicy} objects
+     * Builder class for {@link AudioPolicy} objects.
+     * By default the policy to be created doesn't govern audio focus decisions.
      */
     @SystemApi
     public static class Builder {
@@ -128,6 +133,7 @@
         private Looper mLooper;
         private AudioPolicyFocusListener mFocusListener;
         private AudioPolicyStatusListener mStatusListener;
+        private boolean mIsFocusPolicy = false;
 
         /**
          * Constructs a new Builder with no audio mixes.
@@ -179,6 +185,21 @@
         }
 
         /**
+         * Declares whether this policy will grant and deny audio focus through
+         * the {@link AudioPolicy.AudioPolicyStatusListener}.
+         * If set to {@code true}, it is mandatory to set an
+         * {@link AudioPolicy.AudioPolicyStatusListener} in order to successfully build
+         * an {@code AudioPolicy} instance.
+         * @param enforce true if the policy will govern audio focus decisions.
+         * @return the same Builder instance.
+         */
+        @SystemApi
+        public Builder setIsAudioFocusPolicy(boolean isFocusPolicy) {
+            mIsFocusPolicy = isFocusPolicy;
+            return this;
+        }
+
+        /**
          * Sets the audio policy status listener.
          * @param l a {@link AudioPolicy.AudioPolicyStatusListener}
          */
@@ -187,6 +208,14 @@
             mStatusListener = l;
         }
 
+        /**
+         * Combines all of the attributes that have been set on this {@code Builder} and returns a
+         * new {@link AudioPolicy} object.
+         * @return a new {@code AudioPolicy} object.
+         * @throws IllegalStateException if there is no
+         *     {@link AudioPolicy.AudioPolicyStatusListener} but the policy was configured
+         *     as an audio focus policy with {@link #setIsAudioFocusPolicy(boolean)}.
+         */
         @SystemApi
         public AudioPolicy build() {
             if (mStatusListener != null) {
@@ -195,8 +224,12 @@
                     mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY;
                 }
             }
+            if (mIsFocusPolicy && mFocusListener == null) {
+                throw new IllegalStateException("Cannot be a focus policy without "
+                        + "an AudioPolicyFocusListener");
+            }
             return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
-                    mFocusListener, mStatusListener);
+                    mFocusListener, mStatusListener, mIsFocusPolicy);
         }
     }
 
@@ -402,6 +435,24 @@
     public static abstract class AudioPolicyFocusListener {
         public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {}
         public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {}
+        /**
+         * Called whenever an application requests audio focus.
+         * Only ever called if the {@link AudioPolicy} was built with
+         * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
+         * @param afi information about the focus request and the requester
+         * @param requestResult the result that was returned synchronously by the framework to the
+         *     application, {@link #AUDIOFOCUS_REQUEST_FAILED},or
+         *     {@link #AUDIOFOCUS_REQUEST_DELAYED}.
+         */
+        public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {}
+        /**
+         * Called whenever an application abandons audio focus.
+         * Only ever called if the {@link AudioPolicy} was built with
+         * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
+         * @param afi information about the focus request being abandoned and the original
+         *     requester.
+         */
+        public void onAudioFocusAbandon(AudioFocusInfo afi) {}
     }
 
     private void onPolicyStatusChange() {
@@ -439,6 +490,22 @@
             }
         }
 
+        public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
+            sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
+            if (DEBUG) {
+                Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
+                        + afi.getClientId() + "reqRes=" + requestResult);
+            }
+        }
+
+        public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
+            sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
+            if (DEBUG) {
+                Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
+                        + afi.getClientId());
+            }
+        }
+
         public void notifyMixStateUpdate(String regId, int state) {
             for (AudioMix mix : mConfig.getMixes()) {
                 if (mix.getRegistration().equals(regId)) {
@@ -459,6 +526,8 @@
     private final static int MSG_FOCUS_GRANT = 1;
     private final static int MSG_FOCUS_LOSS = 2;
     private final static int MSG_MIX_STATE_UPDATE = 3;
+    private final static int MSG_FOCUS_REQUEST = 4;
+    private final static int MSG_FOCUS_ABANDON = 5;
 
     private class EventHandler extends Handler {
         public EventHandler(AudioPolicy ap, Looper looper) {
@@ -488,6 +557,20 @@
                         mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
                     }
                     break;
+                case MSG_FOCUS_REQUEST:
+                    if (mFocusListener != null) {
+                        mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
+                    } else { // should never be null, but don't crash
+                        Log.e(TAG, "Invalid null focus listener for focus request event");
+                    }
+                    break;
+                case MSG_FOCUS_ABANDON:
+                    if (mFocusListener != null) { // should never be null
+                        mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj);
+                    } else { // should never be null, but don't crash
+                        Log.e(TAG, "Invalid null focus listener for focus abandon event");
+                    }
+                    break;
                 default:
                     Log.e(TAG, "Unknown event " + msg.what);
             }
diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
index ad8af15..86abbb4 100644
--- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
+++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
@@ -22,9 +22,12 @@
  */
 oneway interface IAudioPolicyCallback {
 
-    // callbacks for audio focus
+    // callbacks for audio focus listening
     void notifyAudioFocusGrant(in AudioFocusInfo afi, int requestResult);
     void notifyAudioFocusLoss(in AudioFocusInfo afi, boolean wasNotified);
+    // callback for audio focus policy
+    void notifyAudioFocusRequest(in AudioFocusInfo afi, int requestResult);
+    void notifyAudioFocusAbandon(in AudioFocusInfo afi);
 
     // callback for mix activity status update
     void notifyMixStateUpdate(in String regId, int state);
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index fc60571..0b27d18 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -16,6 +16,7 @@
 
 package android.media.tv;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
@@ -567,9 +568,10 @@
     }
 
     /**
-     * Common base for the tables of TV programs.
+     * Common columns for the tables of TV programs.
+     * @hide
      */
-    public interface BaseProgramColumns extends BaseTvColumns {
+    interface ProgramColumns {
         /**
          * The title of this TV program.
          *
@@ -835,12 +837,13 @@
     }
 
     /**
-     * Common base for the tables of preview programs.
+     * Common columns for the tables of preview programs.
+     * @hide
      */
-    public interface BasePreviewProgramColumns extends BaseProgramColumns {
+    interface PreviewProgramColumns {
 
         /** @hide */
-        @StringDef({
+        @IntDef({
                 TYPE_MOVIE,
                 TYPE_TV_SERIES,
                 TYPE_TV_SEASON,
@@ -862,87 +865,87 @@
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_MOVIE = "TYPE_MOVIE";
+        int TYPE_MOVIE = 0;
 
         /**
          * The program type for TV series.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+        int TYPE_TV_SERIES = 1;
 
         /**
          * The program type for TV season.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+        int TYPE_TV_SEASON = 2;
 
         /**
          * The program type for TV episode.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+        int TYPE_TV_EPISODE = 3;
 
         /**
          * The program type for clip.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_CLIP = "TYPE_CLIP";
+        int TYPE_CLIP = 4;
 
         /**
          * The program type for event.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_EVENT = "TYPE_EVENT";
+        int TYPE_EVENT = 5;
 
         /**
          * The program type for channel.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_CHANNEL = "TYPE_CHANNEL";
+        int TYPE_CHANNEL = 6;
 
         /**
          * The program type for track.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_TRACK = "TYPE_TRACK";
+        int TYPE_TRACK = 7;
 
         /**
          * The program type for album.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_ALBUM = "TYPE_ALBUM";
+        int TYPE_ALBUM = 8;
 
         /**
          * The program type for artist.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_ARTIST = "TYPE_ARTIST";
+        int TYPE_ARTIST = 9;
 
         /**
          * The program type for playlist.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+        int TYPE_PLAYLIST = 10;
 
         /**
          * The program type for station.
          *
          * @see #COLUMN_TYPE
          */
-        String TYPE_STATION = "TYPE_STATION";
+        int TYPE_STATION = 11;
 
         /** @hide */
-        @StringDef({
+        @IntDef({
                 ASPECT_RATIO_16_9,
                 ASPECT_RATIO_3_2,
                 ASPECT_RATIO_1_1,
@@ -957,7 +960,7 @@
          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
          */
-        String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+        int ASPECT_RATIO_16_9 = 0;
 
         /**
          * The aspect ratio for 3:2.
@@ -965,7 +968,7 @@
          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
          */
-        String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+        int ASPECT_RATIO_3_2 = 1;
 
         /**
          * The aspect ratio for 1:1.
@@ -973,7 +976,7 @@
          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
          */
-        String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+        int ASPECT_RATIO_1_1 = 2;
 
         /**
          * The aspect ratio for 2:3.
@@ -981,10 +984,10 @@
          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
          */
-        String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+        int ASPECT_RATIO_2_3 = 3;
 
         /** @hide */
-        @StringDef({
+        @IntDef({
                 AVAILABILITY_AVAILABLE,
                 AVAILABILITY_FREE_WITH_SUBSCRIPTION,
                 AVAILABILITY_PAID_CONTENT,
@@ -997,15 +1000,14 @@
          *
          * @see #COLUMN_AVAILABILITY
          */
-        String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+        int AVAILABILITY_AVAILABLE = 0;
 
         /**
          * The availability for "free with subscription".
          *
          * @see #COLUMN_AVAILABILITY
          */
-        String AVAILABILITY_FREE_WITH_SUBSCRIPTION =
-                "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+        int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1;
 
         /**
          * The availability for "paid content, either to-own or rental
@@ -1013,72 +1015,72 @@
          *
          * @see #COLUMN_AVAILABILITY
          */
-        String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+        int AVAILABILITY_PAID_CONTENT = 2;
 
         /** @hide */
-        @StringDef({
+        @IntDef({
+                INTERACTION_TYPE_VIEWS,
                 INTERACTION_TYPE_LISTENS,
                 INTERACTION_TYPE_FOLLOWERS,
                 INTERACTION_TYPE_FANS,
                 INTERACTION_TYPE_LIKES,
                 INTERACTION_TYPE_THUMBS,
-                INTERACTION_TYPE_VIEWS,
                 INTERACTION_TYPE_VIEWERS,
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface InteractionType {}
 
         /**
+         * The interaction type for "views".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        int INTERACTION_TYPE_VIEWS = 0;
+
+        /**
          * The interaction type for "listens".
          *
          * @see #COLUMN_INTERACTION_TYPE
          */
-        String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+        int INTERACTION_TYPE_LISTENS = 1;
 
         /**
          * The interaction type for "followers".
          *
          * @see #COLUMN_INTERACTION_TYPE
          */
-        String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+        int INTERACTION_TYPE_FOLLOWERS = 2;
 
         /**
          * The interaction type for "fans".
          *
          * @see #COLUMN_INTERACTION_TYPE
          */
-        String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+        int INTERACTION_TYPE_FANS = 3;
 
         /**
          * The interaction type for "likes".
          *
          * @see #COLUMN_INTERACTION_TYPE
          */
-        String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+        int INTERACTION_TYPE_LIKES = 4;
 
         /**
          * The interaction type for "thumbs".
          *
          * @see #COLUMN_INTERACTION_TYPE
          */
-        String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
-
-        /**
-         * The interaction type for "views".
-         *
-         * @see #COLUMN_INTERACTION_TYPE
-         */
-        String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+        int INTERACTION_TYPE_THUMBS = 5;
 
         /**
          * The interaction type for "viewers".
          *
          * @see #COLUMN_INTERACTION_TYPE
          */
-        String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+        int INTERACTION_TYPE_VIEWERS = 6;
 
         /** @hide */
-        @StringDef({
+        @IntDef({
                 REVIEW_RATING_STYLE_STARS,
                 REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
                 REVIEW_RATING_STYLE_PERCENTAGE,
@@ -1091,23 +1093,21 @@
          *
          * @see #COLUMN_REVIEW_RATING_STYLE
          */
-        String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+        int REVIEW_RATING_STYLE_STARS = 0;
 
         /**
          * The review rating style for thumbs-up and thumbs-down rating.
          *
          * @see #COLUMN_REVIEW_RATING_STYLE
          */
-        String REVIEW_RATING_STYLE_THUMBS_UP_DOWN =
-                "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+        int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1;
 
         /**
          * The review rating style for 0 to 100 point system.
          *
          * @see #COLUMN_REVIEW_RATING_STYLE
          */
-        String REVIEW_RATING_STYLE_PERCENTAGE =
-                "REVIEW_RATING_STYLE_PERCENTAGE";
+        int REVIEW_RATING_STYLE_PERCENTAGE = 2;
 
         /**
          * The type of this program content.
@@ -1129,7 +1129,7 @@
          * <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
          * channel.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          */
         String COLUMN_TYPE = "type";
 
@@ -1142,7 +1142,7 @@
          * {@link #ASPECT_RATIO_1_1}, and
          * {@link #ASPECT_RATIO_2_3}.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          */
         String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
 
@@ -1155,7 +1155,7 @@
          * {@link #ASPECT_RATIO_1_1}, and
          * {@link #ASPECT_RATIO_2_3}.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          */
         String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
 
@@ -1188,7 +1188,7 @@
          * {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
          * {@link #AVAILABILITY_PAID_CONTENT}.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          */
         String COLUMN_AVAILABILITY = "availability";
 
@@ -1327,15 +1327,15 @@
          * The type of interaction for this TV program.
          *
          * <p> The value should match one of the followings:
+         * {@link #INTERACTION_TYPE_VIEWS},
          * {@link #INTERACTION_TYPE_LISTENS},
          * {@link #INTERACTION_TYPE_FOLLOWERS},
          * {@link #INTERACTION_TYPE_FANS},
          * {@link #INTERACTION_TYPE_LIKES},
-         * {@link #INTERACTION_TYPE_THUMBS},
-         * {@link #INTERACTION_TYPE_VIEWS}, and
+         * {@link #INTERACTION_TYPE_THUMBS}, and
          * {@link #INTERACTION_TYPE_VIEWERS}.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          * @see #COLUMN_INTERACTION_COUNT
          */
         String COLUMN_INTERACTION_TYPE = "interaction_type";
@@ -1363,7 +1363,7 @@
          * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
          * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          * @see #COLUMN_REVIEW_RATING
          */
         String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
@@ -2229,7 +2229,7 @@
      * <p>By default, the query results will be sorted by
      * {@link Programs#COLUMN_START_TIME_UTC_MILLIS} in ascending order.
      */
-    public static final class Programs implements BaseProgramColumns {
+    public static final class Programs implements BaseTvColumns, ProgramColumns {
 
         /** The content:// style URI for this table. */
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2543,7 +2543,7 @@
      * <p>By default, the query results will be sorted by {@link #COLUMN_START_TIME_UTC_MILLIS} in
      * ascending order.
      */
-    public static final class RecordedPrograms implements BaseProgramColumns {
+    public static final class RecordedPrograms implements BaseTvColumns, ProgramColumns {
 
         /** The content:// style URI for this table. */
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2665,7 +2665,8 @@
     /**
      * Column definitions for the preview TV programs table.
      */
-    public static final class PreviewPrograms implements BasePreviewProgramColumns {
+    public static final class PreviewPrograms implements BaseTvColumns, ProgramColumns,
+        PreviewProgramColumns {
 
         /** The content:// style URI for this table. */
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2711,7 +2712,8 @@
     /**
      * Column definitions for the "watch next" TV programs table.
      */
-    public static final class WatchNextPrograms implements BasePreviewProgramColumns {
+    public static final class WatchNextPrograms implements BaseTvColumns, ProgramColumns,
+        PreviewProgramColumns {
 
         /** The content:// style URI for this table. */
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
@@ -2724,7 +2726,7 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
 
         /** @hide */
-        @StringDef({
+        @IntDef({
                 WATCH_NEXT_TYPE_CONTINUE,
                 WATCH_NEXT_TYPE_NEXT,
                 WATCH_NEXT_TYPE_NEW,
@@ -2739,7 +2741,7 @@
          *
          * @see #COLUMN_WATCH_NEXT_TYPE
          */
-        public static final String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+        public static final int WATCH_NEXT_TYPE_CONTINUE = 0;
 
         /**
          * The watch next type for NEXT. Use this type when the user has watched one or more
@@ -2749,7 +2751,7 @@
          *
          * @see #COLUMN_WATCH_NEXT_TYPE
          */
-        public static final String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+        public static final int WATCH_NEXT_TYPE_NEXT = 1;
 
         /**
          * The watch next type for NEW. Use this type when the user had watched all of the available
@@ -2759,7 +2761,7 @@
          *
          * @see #COLUMN_WATCH_NEXT_TYPE
          */
-        public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+        public static final int WATCH_NEXT_TYPE_NEW = 2;
 
         /**
          * The watch next type for WATCHLIST. Use this type when the user has elected to explicitly
@@ -2768,7 +2770,7 @@
          *
          * @see #COLUMN_WATCH_NEXT_TYPE
          */
-        public static final String WATCH_NEXT_TYPE_WATCHLIST = "WATCH_NEXT_TYPE_WATCHLIST";
+        public static final int WATCH_NEXT_TYPE_WATCHLIST = 3;
 
         /**
          * The "watch next" type of this program content.
@@ -2781,7 +2783,7 @@
          *
          * <p>This is a required field.
          *
-         * <p>Type: TEXT
+         * <p>Type: INTEGER
          */
         public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
 
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index d5d9fc9..0149d76 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -342,7 +342,7 @@
     }
     // New GraphicBuffer object doesn't own the handle, thus the native buffer
     // won't be freed when this object is destroyed.
-    sp<GraphicBuffer> buffer(new GraphicBuffer(anb, /*keepOwnership*/false));
+    sp<GraphicBuffer> buffer(GraphicBuffer::from(anb));
 
     // Note that:
     // 1. No need to lock buffer now, will only lock it when the first getPlanes() is called.
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index c7bed9b..c82a1f6 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -153,6 +153,7 @@
     ANativeWindow_acquire;
     ANativeWindow_fromSurface;
     ANativeWindow_fromSurfaceTexture; # introduced-arm=13 introduced-mips=13 introduced-x86=13
+    ANativeWindow_toSurface; # introduced=26
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
     ANativeWindow_getWidth;
diff --git a/native/android/native_window_jni.cpp b/native/android/native_window_jni.cpp
index dc30405..859c550 100644
--- a/native/android/native_window_jni.cpp
+++ b/native/android/native_window_jni.cpp
@@ -20,6 +20,7 @@
 #include <android/native_window.h>
 #include <system/window.h>
 
+#include <gui/Surface.h>
 #include <utils/StrongPointer.h>
 
 #include <android_runtime/android_view_Surface.h>
@@ -33,3 +34,11 @@
     }
     return win.get();
 }
+
+jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) {
+    if (window == NULL) {
+        return NULL;
+    }
+    sp<Surface> surface = static_cast<Surface*>(window);
+    return android_view_Surface_createFromSurface(env, surface);
+}
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index f9342b7..fa5c3ff 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -6,6 +6,7 @@
     <string name="no_data_notification_id">Your mobile data has been deactivated</string>
     <string name="portal_notification_detail">Tap to visit the %s website</string>
     <string name="no_data_notification_detail">Please contact your service provider %s</string>
+    <string name="mobile_data_status_notification_channel_name">Mobile data status</string>
     <string name="action_bar_label">Sign in to mobile network</string>
     <string name="ssl_error_warning">The network you&#8217;re trying to join has security issues.</string>
     <string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 73ff3a9..7fd1601 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -16,6 +16,7 @@
 package com.android.carrierdefaultapp;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -35,6 +36,7 @@
 
     private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
     private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
+    private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status";
     private static final int PORTAL_NOTIFICATION_ID = 0;
     private static final int NO_DATA_NOTIFICATION_ID = 1;
     private static boolean ENABLE = true;
@@ -150,9 +152,18 @@
     private static Notification getNotification(Context context, int titleId, int textId,
                                          PendingIntent pendingIntent) {
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+        final NotificationManager notificationManager = context.getSystemService(
+                NotificationManager.class);
         final Resources resources = context.getResources();
         final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
                 resources.getString(R.string.android_system_label));
+        /* Creates the notification channel and registers it with NotificationManager. If a channel
+         * with the same ID is already registered, NotificationManager will ignore this call.
+         */
+        notificationManager.createNotificationChannel(new NotificationChannel(
+                NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
+                resources.getString(R.string.mobile_data_status_notification_channel_name),
+                NotificationManager.IMPORTANCE_DEFAULT));
         Notification.Builder builder = new Notification.Builder(context)
                 .setContentTitle(resources.getString(titleId))
                 .setContentText(String.format(resources.getString(textId),
@@ -167,7 +178,8 @@
                 .setLocalOnly(true)
                 .setWhen(System.currentTimeMillis())
                 .setShowWhen(false)
-                .setExtras(extras);
+                .setExtras(extras)
+                .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS);
 
         if (pendingIntent != null) {
             builder.setContentIntent(pendingIntent);
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f14d0d1..ad985c7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -928,4 +928,18 @@
          [CHAR LIMIT=35] -->
     <string name="use_system_language_to_select_input_method_subtypes">Use system languages</string>
 
+    <!-- Toast that settings for an application is failed to open. -->
+    <string name="failed_to_open_app_settings_toast">Failed to open settings for <xliff:g id="spell_application_name">%1$s</xliff:g></string>
+
+    <!-- Warning message about security implications of enabling an input method, displayed as a dialog
+         message when the user selects to enable an IME. -->
+    <string name="ime_security_warning">This input method may be able to collect
+        all the text you type, including personal data like passwords and credit
+        card numbers.  It comes from the app
+        <xliff:g id="ime_application_name">%1$s</xliff:g>.
+        Use this input method?</string>
+
+    <!-- [CHAR LIMIT=NONE] Dialog body explaining that the app just selected by the user will not work after a reboot until until after the user enters their credentials, such as a PIN or password. -->
+    <string name="direct_boot_unaware_dialog_message">Note: After a reboot, this app can\'t start until you unlock your phone</string>
+
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index c2ce7c9..8833fb8c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -1394,7 +1394,9 @@
 
         @Override
         public boolean filterApp(AppEntry entry) {
-            if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+            if (AppUtils.isInstant(entry.info)) {
+                return false;
+            } else if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                 return true;
             } else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                 return true;
@@ -1407,6 +1409,23 @@
         }
     };
 
+    /**
+     * Displays a combined list with "downloaded" and "visible in launcher" apps only.
+     */
+    public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT = new AppFilter() {
+
+        @Override
+        public void init() {
+        }
+
+        @Override
+        public boolean filterApp(AppEntry entry) {
+            return AppUtils.isInstant(entry.info)
+                    || FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(entry);
+        }
+
+    };
+
     public static final AppFilter FILTER_THIRD_PARTY = new AppFilter() {
         @Override
         public void init() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
index 69b45e5..9ea7a4a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
@@ -71,14 +71,15 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        if (intent.getAction() == null || !intent.getAction().equals(INTENT_DISCOVERABLE_TIMEOUT)) {
+            return;
+        }
         LocalBluetoothAdapter localBluetoothAdapter = LocalBluetoothAdapter.getInstance();
-
-         if(localBluetoothAdapter != null  &&
+        if(localBluetoothAdapter != null  &&
             localBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
             Log.d(TAG, "Disable discoverable...");
-
             localBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
-         } else {
+        } else {
             Log.e(TAG, "localBluetoothAdapter is NULL!!");
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index a3ae926..abd4e29 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -103,7 +103,7 @@
      */
     public String getName(BluetoothDevice device) {
         CachedBluetoothDevice cachedDevice = findDevice(device);
-        if (cachedDevice != null) {
+        if (cachedDevice != null && cachedDevice.getName() != null) {
             return cachedDevice.getName();
         }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index 40abb6c..88f133c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -41,8 +41,8 @@
         long privateTotalBytes = 0;
         for (VolumeInfo info : sm.getVolumes()) {
             if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
-                privateTotalBytes += stats.getTotalBytes(info.getFsUuid());
-                privateFreeBytes += stats.getFreeBytes(info.getFsUuid());
+                privateTotalBytes += sm.getTotalBytes(stats, info);
+                privateFreeBytes += sm.getFreeBytes(stats, info);
             }
         }
         return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
index 320494c..11060e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.deviceinfo;
 
+import android.app.usage.StorageStatsManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 
@@ -46,4 +47,14 @@
     public VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume) {
         return mStorageManager.findEmulatedForPrivate(privateVolume);
     }
+
+    @Override
+    public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) {
+        return stats.getTotalBytes(volume.getFsUuid());
+    }
+
+    @Override
+    public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) {
+        return stats.getFreeBytes(volume.getFsUuid());
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
index 646c42f..e5d85d1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.deviceinfo;
 
+import android.app.usage.StorageStatsManager;
 import android.os.storage.VolumeInfo;
 
 import java.util.List;
@@ -39,4 +40,18 @@
      * Returns the emulated volume for a given private volume.
      */
     VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume);
+
+    /**
+     * Returns the total bytes for a given storage volume.
+     *
+     * @pre The volume is a private volume and is readable.
+     */
+    long getTotalBytes(StorageStatsManager stats, VolumeInfo volume);
+
+    /**
+     * Returns the free bytes for a given storage volume.
+     *
+     * @pre The volume is a private volume and is readable.
+     */
+    long getFreeBytes(StorageStatsManager stats, VolumeInfo volume);
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
new file mode 100755
index 0000000..1bbc878b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.inputmethod;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.Toast;
+
+import com.android.internal.inputmethod.InputMethodUtils;
+import com.android.settingslib.R;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import java.text.Collator;
+import java.util.List;
+
+/**
+ * Input method preference.
+ *
+ * This preference represents an IME. It is used for two purposes. 1) An instance with a switch
+ * is used to enable or disable the IME. 2) An instance without a switch is used to invoke the
+ * setting activity of the IME.
+ */
+public class InputMethodPreference extends RestrictedSwitchPreference implements OnPreferenceClickListener,
+        OnPreferenceChangeListener {
+    private static final String TAG = InputMethodPreference.class.getSimpleName();
+    private static final String EMPTY_TEXT = "";
+    private static final int NO_WIDGET = 0;
+
+    public interface OnSavePreferenceListener {
+        /**
+         * Called when this preference needs to be saved its state.
+         *
+         * Note that this preference is non-persistent and needs explicitly to be saved its state.
+         * Because changing one IME state may change other IMEs' state, this is a place to update
+         * other IMEs' state as well.
+         *
+         * @param pref This preference.
+         */
+        void onSaveInputMethodPreference(InputMethodPreference pref);
+    }
+
+    private final InputMethodInfo mImi;
+    private final boolean mHasPriorityInSorting;
+    private final OnSavePreferenceListener mOnSaveListener;
+    private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
+    private final boolean mIsAllowedByOrganization;
+
+    private AlertDialog mDialog = null;
+
+    /**
+     * A preference entry of an input method.
+     *
+     * @param context The Context this is associated with.
+     * @param imi The {@link InputMethodInfo} of this preference.
+     * @param isImeEnabler true if this preference is the IME enabler that has enable/disable
+     *     switches for all available IMEs, not the list of enabled IMEs.
+     * @param isAllowedByOrganization false if the IME has been disabled by a device or profile
+     *     owner.
+     * @param onSaveListener The listener called when this preference has been changed and needs
+     *     to save the state to shared preference.
+     */
+    public InputMethodPreference(final Context context, final InputMethodInfo imi,
+            final boolean isImeEnabler, final boolean isAllowedByOrganization,
+            final OnSavePreferenceListener onSaveListener) {
+        super(context);
+        setPersistent(false);
+        mImi = imi;
+        mIsAllowedByOrganization = isAllowedByOrganization;
+        mOnSaveListener = onSaveListener;
+        if (!isImeEnabler) {
+            // Remove switch widget.
+            setWidgetLayoutResource(NO_WIDGET);
+        }
+        // Disable on/off switch texts.
+        setSwitchTextOn(EMPTY_TEXT);
+        setSwitchTextOff(EMPTY_TEXT);
+        setKey(imi.getId());
+        setTitle(imi.loadLabel(context.getPackageManager()));
+        final String settingsActivity = imi.getSettingsActivity();
+        if (TextUtils.isEmpty(settingsActivity)) {
+            setIntent(null);
+        } else {
+            // Set an intent to invoke settings activity of an input method.
+            final Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setClassName(imi.getPackageName(), settingsActivity);
+            setIntent(intent);
+        }
+        mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(context);
+        mHasPriorityInSorting = InputMethodUtils.isSystemIme(imi)
+                && mInputMethodSettingValues.isValidSystemNonAuxAsciiCapableIme(imi, context);
+        setOnPreferenceClickListener(this);
+        setOnPreferenceChangeListener(this);
+    }
+
+    public InputMethodInfo getInputMethodInfo() {
+        return mImi;
+    }
+
+    private boolean isImeEnabler() {
+        // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the
+        // switch widget at constructor.
+        return getWidgetLayoutResource() != NO_WIDGET;
+    }
+
+    @Override
+    public boolean onPreferenceChange(final Preference preference, final Object newValue) {
+        // Always returns false to prevent default behavior.
+        // See {@link TwoStatePreference#onClick()}.
+        if (!isImeEnabler()) {
+            // Prevent disabling an IME because this preference is for invoking a settings activity.
+            return false;
+        }
+        if (isChecked()) {
+            // Disable this IME.
+            setCheckedInternal(false);
+            return false;
+        }
+        if (InputMethodUtils.isSystemIme(mImi)) {
+            // Enable a system IME. No need to show a security warning dialog,
+            // but we might need to prompt if it's not Direct Boot aware.
+            // TV doesn't doesn't need to worry about this, but other platforms should show
+            // a warning.
+            if (mImi.getServiceInfo().directBootAware || isTv()) {
+                setCheckedInternal(true);
+            } else if (!isTv()){
+                showDirectBootWarnDialog();
+            }
+        } else {
+            // Once security is confirmed, we might prompt if the IME isn't
+            // Direct Boot aware.
+            showSecurityWarnDialog();
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onPreferenceClick(final Preference preference) {
+        // Always returns true to prevent invoking an intent without catching exceptions.
+        // See {@link Preference#performClick(PreferenceScreen)}/
+        if (isImeEnabler()) {
+            // Prevent invoking a settings activity because this preference is for enabling and
+            // disabling an input method.
+            return true;
+        }
+        final Context context = getContext();
+        try {
+            final Intent intent = getIntent();
+            if (intent != null) {
+                // Invoke a settings activity of an input method.
+                context.startActivity(intent);
+            }
+        } catch (final ActivityNotFoundException e) {
+            Log.d(TAG, "IME's Settings Activity Not Found", e);
+            final String message = context.getString(
+                    R.string.failed_to_open_app_settings_toast,
+                    mImi.loadLabel(context.getPackageManager()));
+            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
+        }
+        return true;
+    }
+
+    public void updatePreferenceViews() {
+        final boolean isAlwaysChecked = mInputMethodSettingValues.isAlwaysCheckedIme(
+                mImi, getContext());
+        // When this preference has a switch and an input method should be always enabled,
+        // this preference should be disabled to prevent accidentally disabling an input method.
+        // This preference should also be disabled in case the admin does not allow this input
+        // method.
+        if (isAlwaysChecked && isImeEnabler()) {
+            setDisabledByAdmin(null);
+            setEnabled(false);
+        } else if (!mIsAllowedByOrganization) {
+            EnforcedAdmin admin =
+                    RestrictedLockUtils.checkIfInputMethodDisallowed(getContext(),
+                            mImi.getPackageName(), UserHandle.myUserId());
+            setDisabledByAdmin(admin);
+        } else {
+            setEnabled(true);
+        }
+        setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
+        if (!isDisabledByAdmin()) {
+            setSummary(getSummaryString());
+        }
+    }
+
+    private InputMethodManager getInputMethodManager() {
+        return (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+    }
+
+    private String getSummaryString() {
+        final InputMethodManager imm = getInputMethodManager();
+        final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
+        return InputMethodAndSubtypeUtil.getSubtypeLocaleNameListAsSentence(
+                subtypes, getContext(), mImi);
+    }
+
+    private void setCheckedInternal(boolean checked) {
+        super.setChecked(checked);
+        mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
+        notifyChanged();
+    }
+
+    private void showSecurityWarnDialog() {
+        if (mDialog != null && mDialog.isShowing()) {
+            mDialog.dismiss();
+        }
+        final Context context = getContext();
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setCancelable(true /* cancelable */);
+        builder.setTitle(android.R.string.dialog_alert_title);
+        final CharSequence label = mImi.getServiceInfo().applicationInfo.loadLabel(
+                context.getPackageManager());
+        builder.setMessage(context.getString(R.string.ime_security_warning, label));
+        builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
+            // The user confirmed to enable a 3rd party IME, but we might
+            // need to prompt if it's not Direct Boot aware.
+            // TV doesn't doesn't need to worry about this, but other platforms should show
+            // a warning.
+            if (mImi.getServiceInfo().directBootAware || isTv()) {
+                setCheckedInternal(true);
+            } else {
+                showDirectBootWarnDialog();
+            }
+        });
+        builder.setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+            // The user canceled to enable a 3rd party IME.
+            setCheckedInternal(false);
+        });
+        mDialog = builder.create();
+        mDialog.show();
+    }
+
+    private boolean isTv() {
+        return (getContext().getResources().getConfiguration().uiMode
+                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION;
+    }
+
+    private void showDirectBootWarnDialog() {
+        if (mDialog != null && mDialog.isShowing()) {
+            mDialog.dismiss();
+        }
+        final Context context = getContext();
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setCancelable(true /* cancelable */);
+        builder.setMessage(context.getText(R.string.direct_boot_unaware_dialog_message));
+        builder.setPositiveButton(android.R.string.ok, (dialog, which) -> setCheckedInternal(true));
+        builder.setNegativeButton(android.R.string.cancel,
+                (dialog, which) -> setCheckedInternal(false));
+        mDialog = builder.create();
+        mDialog.show();
+    }
+
+    public int compareTo(final InputMethodPreference rhs, final Collator collator) {
+        if (this == rhs) {
+            return 0;
+        }
+        if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
+            final CharSequence t0 = getTitle();
+            final CharSequence t1 = rhs.getTitle();
+            if (TextUtils.isEmpty(t0)) {
+                return 1;
+            }
+            if (TextUtils.isEmpty(t1)) {
+                return -1;
+            }
+            return collator.compare(t0.toString(), t1.toString());
+        }
+        // Prefer always checked system IMEs
+        return mHasPriorityInSorting ? -1 : 1;
+    }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index e204a3a..6a029f0 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -110,6 +110,70 @@
     }
 
     @Test
+    public void testDownloadAndLauncherAndInstantAcceptsCorrectApps() {
+        // should include instant apps
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = false;
+        when(mEntry.info.isInstantApp()).thenReturn(true);
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+                .isTrue();
+
+        // should included updated system apps
+        when(mEntry.info.isInstantApp()).thenReturn(false);
+        mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+                .isTrue();
+
+        // should not include system apps other than the home app
+        mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = false;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+                .isFalse();
+
+        // should include the home app
+        mEntry.isHomeApp = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+                .isTrue();
+
+        // should include any System app with a launcher entry
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT.filterApp(mEntry))
+                .isTrue();
+    }
+
+    @Test
+    public void testDownloadAndLauncherAcceptsCorrectApps() {
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = false;
+
+        // should included updated system apps
+        when(mEntry.info.isInstantApp()).thenReturn(false);
+        mEntry.info.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+                .isTrue();
+
+        // should not include system apps other than the home app
+        mEntry.info.flags = ApplicationInfo.FLAG_SYSTEM;
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = false;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+                .isFalse();
+
+        // should include the home app
+        mEntry.isHomeApp = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+                .isTrue();
+
+        // should include any System app with a launcher entry
+        mEntry.isHomeApp = false;
+        mEntry.hasLauncherEntry = true;
+        assertThat(ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(mEntry))
+                .isTrue();
+    }
+
+    @Test
     public void testInstantFilterAcceptsInstantApp() {
         when(mEntry.info.isInstantApp()).thenReturn(true);
         assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isTrue();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 0d0ddf2..1f559e4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2798,7 +2798,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 143;
+            private static final int SETTINGS_VERSION = 144;
 
             private final int mUserId;
 
@@ -3324,7 +3324,7 @@
                 }
 
                 if (currentVersion == 141) {
-                    // Version 141: We added the notion of a default and whether the system set
+                    // Version 142: We added the notion of a default and whether the system set
                     // the setting. This is used for resetting the internal state and we need
                     // to make sure this value is updated for the existing settings, otherwise
                     // we would delete system set settings while they should stay unmodified.
@@ -3344,7 +3344,7 @@
                 }
 
                 if (currentVersion == 142) {
-                    // Version 142: Set a default value for Wi-Fi wakeup feature.
+                    // Version 143: Set a default value for Wi-Fi wakeup feature.
                     if (userId == UserHandle.USER_SYSTEM) {
                         final SettingsState globalSettings = getGlobalSettingsLocked();
                         Setting currentSetting = globalSettings.getSettingLocked(
@@ -3361,6 +3361,27 @@
                     currentVersion = 143;
                 }
 
+                if (currentVersion == 143) {
+                    // Version 144: Set a default value for Autofill service.
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+                    final Setting currentSetting = secureSettings
+                            .getSettingLocked(Settings.Secure.AUTOFILL_SERVICE);
+                    if (currentSetting.isNull()) {
+                        final String defaultValue = getContext().getResources().getString(
+                                com.android.internal.R.string.config_defaultAutofillService);
+                        if (defaultValue != null) {
+                            Slog.d(LOG_TAG, "Setting [" + defaultValue + "] as Autofill Service "
+                                    + "for user " + userId);
+                            secureSettings.insertSettingLocked(Settings.Secure.AUTOFILL_SERVICE,
+                                    defaultValue, null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                        }
+                    }
+
+                    currentVersion = 144;
+                }
+
+                // vXXX: Add new settings above this point.
+
                 if (currentVersion != newVersion) {
                     Slog.wtf("SettingsProvider", "warning: upgrading settings database to version "
                             + newVersion + " left it at "
@@ -3372,8 +3393,6 @@
                     }
                 }
 
-                // vXXX: Add new settings above this point.
-
                 // Return the current version.
                 return currentVersion;
             }
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ad39f54..a8cf3da 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1962,4 +1962,31 @@
     <!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
     <string name="mobile_data">Mobile data</string>
 
+    <!-- Label for when wifi is off in QS detail panel [CHAR LIMIT=NONE] -->
+    <string name="wifi_is_off">Wi-Fi is off</string>
+
+    <!-- Label for when bluetooth is off in QS detail panel [CHAR LIMIT=NONE] -->
+    <string name="bt_is_off">Bluetooth is off</string>
+
+    <!-- Label for when Do not disturb is off in QS detail panel [CHAR LIMIT=NONE] -->
+    <string name="dnd_is_off">Do Not Disturb is off</string>
+
+    <!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] -->
+    <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>). Keep current settings?</string>
+
+    <!-- Prompt for when Do not disturb is on from app in QS [CHAR LIMIT=NONE] -->
+    <string name="qs_dnd_prompt_app">Do Not Disturb was turned on by an app (<xliff:g name="app">%s</xliff:g>). Keep current settings?</string>
+
+    <!-- Prompt for when Do not disturb is on from automatic rule or app in QS [CHAR LIMIT=NONE] -->
+    <string name="qs_dnd_prompt_auto_rule_app">Do Not Disturb was turned on by an automatic rule or app. Keep current settings?</string>
+
+    <!-- Description of Do Not Disturb option in QS that ends at the specified time[CHAR LIMIT=20] -->
+    <string name="qs_dnd_until">Until <xliff:g name="time">%s</xliff:g></string>
+
+    <!-- Do Not Disturb button to keep the current settings [CHAR LIMIT=20] -->
+    <string name="qs_dnd_keep">Keep</string>
+
+    <!-- Do Not Disturb button to change the current settings [CHAR LIMIT=20] -->
+    <string name="qs_dnd_replace">Replace</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 2655837..80b4da8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -34,9 +34,11 @@
 import android.widget.TextClock;
 import android.widget.TextView;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ChargingView;
 
+import java.util.Arrays;
 import java.util.Locale;
 
 public class KeyguardStatusView extends GridLayout {
@@ -53,6 +55,10 @@
     private ViewGroup mClockContainer;
     private ChargingView mBatteryDoze;
 
+    private View[] mVisibleInDoze;
+    private boolean mPulsing;
+    private boolean mDark;
+
     private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
@@ -117,6 +123,7 @@
         mClockView.setShowCurrentUserTime(true);
         mOwnerInfo = (TextView) findViewById(R.id.owner_info);
         mBatteryDoze = (ChargingView) findViewById(R.id.battery_doze);
+        mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
 
         boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
         setEnableMarquee(shouldMarquee);
@@ -273,14 +280,28 @@
     }
 
     public void setDark(boolean dark) {
+        mDark = dark;
+
         final int N = mClockContainer.getChildCount();
         for (int i = 0; i < N; i++) {
             View child = mClockContainer.getChildAt(i);
-            if (child == mClockView || child == mBatteryDoze) {
+            if (ArrayUtils.contains(mVisibleInDoze, child)) {
                 continue;
             }
             child.setAlpha(dark ? 0 : 1);
         }
+        updateDozeVisibleViews();
         mBatteryDoze.setDark(dark);
     }
+
+    public void setPulsing(boolean pulsing) {
+        mPulsing = pulsing;
+        updateDozeVisibleViews();
+    }
+
+    private void updateDozeVisibleViews() {
+        for (View child : mVisibleInDoze) {
+            child.setAlpha(mDark && mPulsing ? 0.5f : 1);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index bcf1957..fbd9f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -86,6 +86,7 @@
     private static final float DISABLED_ACTION_ALPHA = 0.54f;
 
     private boolean mMenuVisible;
+    private boolean mAllowMenuTimeout = true;
     private final List<RemoteAction> mActions = new ArrayList<>();
     private View mViewRoot;
     private Drawable mBackgroundDrawable;
@@ -190,7 +191,9 @@
 
     @Override
     public void onUserInteraction() {
-        repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+        if (mAllowMenuTimeout) {
+            repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY);
+        }
     }
 
     @Override
@@ -255,6 +258,7 @@
     }
 
     private void showMenu(Rect stackBounds, Rect movementBounds, boolean allowMenuTimeout) {
+        mAllowMenuTimeout = allowMenuTimeout;
         if (!mMenuVisible) {
             updateActionViews(stackBounds);
             if (mMenuContainerAnimator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 9efe224..d2a2919 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -242,7 +242,7 @@
         mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
         mDetailSettingsButton.setOnClickListener(v -> {
             Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
-                    mDetailAdapter.getMetricsCategory());
+                    adapter.getMetricsCategory());
             Dependency.get(ActivityStarter.class)
                     .postStartActivityDismissingKeyguard(settingsIntent, 0);
         });
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 4b2c20f..5b9d95d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2014 The Android Open Source Project
  *
@@ -358,9 +359,8 @@
         @Override
         public void onClick(View widget) {
             final Intent intent = new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
             mDialog.dismiss();
-            mContext.startActivity(intent);
+            mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
 
         @Override
@@ -373,9 +373,8 @@
         @Override
         public void onClick(View widget) {
             final Intent intent = new Intent(Settings.ACTION_VPN_SETTINGS);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
             mDialog.dismiss();
-            mContext.startActivity(intent);
+            mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 1c71da0..3a43d30 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -355,9 +355,10 @@
                 rti.firstActiveTime = rti.lastActiveTime = i;
                 if (i % 2 == 0) {
                     rti.taskDescription = new ActivityManager.TaskDescription(description,
-                        Bitmap.createBitmap(mDummyIcon), null,
-                        0xFF000000 | (0xFFFFFF & new Random().nextInt()),
-                        0xFF000000 | (0xFFFFFF & new Random().nextInt()));
+                            Bitmap.createBitmap(mDummyIcon), null,
+                            0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+                            0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+                            0, 0);
                 } else {
                     rti.taskDescription = new ActivityManager.TaskDescription();
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 97506e6..0ee3e19 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -58,6 +58,7 @@
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
@@ -108,9 +109,6 @@
     private static final Interpolator IME_ADJUST_INTERPOLATOR =
             new PathInterpolator(0.2f, 0f, 0.1f, 1f);
 
-    private static final long ONE_MS_IN_NS = 1000000;
-    private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
-
     private static final int MSG_RESIZE_STACK = 0;
 
     private DividerHandleView mHandle;
@@ -161,12 +159,7 @@
     private boolean mHomeStackResizable;
     private boolean mAdjustedForIme;
     private DividerState mState;
-
-    /**
-     * The offset between vsync-app and vsync-surfaceflinger. See
-     * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
-     */
-    private long mSurfaceFlingerOffsetMs;
+    private SurfaceFlingerVsyncChoreographer mSfChoreographer;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -319,7 +312,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         EventBus.getDefault().register(this);
-        mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs();
+        mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, getDisplay());
     }
 
     @Override
@@ -328,25 +321,6 @@
         EventBus.getDefault().unregister(this);
     }
 
-    /**
-     * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
-     * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the
-     * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after,
-     * which leads to jank. Figure out this difference here and then post all the touch/animation
-     * events to start being processed at vsync-sf.
-     *
-     * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
-     */
-    private long calculateAppSurfaceFlingerVsyncOffsetMs() {
-        Display display = getDisplay();
-
-        // Calculate vsync offset from SurfaceFlinger.
-        // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
-        long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
-        long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
-        return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
-    }
-
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         if (mStableInsets.left != insets.getStableInsetLeft()
@@ -630,8 +604,8 @@
                     delay = endDelay;
                 } else if (mCancelled) {
                     delay = 0;
-                } else if (mSurfaceFlingerOffsetMs != 0) {
-                    delay = mSurfaceFlingerOffsetMs;
+                } else if (mSfChoreographer.getSurfaceFlingerOffsetMs() > 0) {
+                    delay = mSfChoreographer.getSurfaceFlingerOffsetMs();
                 }
                 if (delay == 0) {
                     endAction.run();
@@ -916,14 +890,10 @@
     }
 
     public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) {
-        if (mSurfaceFlingerOffsetMs != 0) {
-            Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
-                    taskSnapTarget);
-            message.setAsynchronous(true);
-            mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs);
-        } else {
-            resizeStack(position, taskPosition, taskSnapTarget);
-        }
+        Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
+                taskSnapTarget);
+        message.setAsynchronous(true);
+        mSfChoreographer.scheduleAtSfVsync(mHandler, message);
     }
 
     public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 21a0dc9..8298f35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -228,6 +228,7 @@
         // Settings button.
         final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
         if (mAppUid >= 0 && onSettingsClick != null) {
+            settingsButton.setVisibility(View.VISIBLE);
             final int appUidF = mAppUid;
             settingsButton.setOnClickListener(
                     (View view) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 5055dda..bb82b60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -120,6 +120,9 @@
     @Override
     public void createMenu(ViewGroup parent) {
         mParent = (ExpandableNotificationRow) parent;
+        if (mMenuContainer != null) {
+            mMenuContainer.removeAllViews();
+        }
         mMenuContainer = new FrameLayout(mContext);
         for (int i = 0; i < mMenuItems.size(); i++) {
             addMenuView(mMenuItems.get(i), mMenuContainer);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 8da17fa..8042321 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -23,7 +23,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import com.android.internal.widget.CachingIconView;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.ViewInvertHelper;
@@ -127,12 +126,8 @@
         super.setDark(dark, fade, delay);
         if (mDark == dark) return;
         mDark = dark;
-        if (fade) {
-            mViewInvertHelper.fade(dark, delay);
-        } else {
-            mViewInvertHelper.update(dark);
-        }
-        mShelfIcons.setAmbient(dark);
+        mShelfIcons.setDark(dark, fade, delay);
+        updateInteractiveness();
     }
 
     @Override
@@ -167,7 +162,7 @@
             openedAmount = Math.min(1.0f, openedAmount);
             mShelfState.openedAmount = openedAmount;
             mShelfState.clipTopAmount = 0;
-            mShelfState.alpha = 1.0f;
+            mShelfState.alpha = mAmbientState.isPulsing() ? 0 : 1;
             mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
             mShelfState.shadowAlpha = 1.0f;
             mShelfState.hideSensitive = false;
@@ -576,7 +571,8 @@
     }
 
     private void updateInteractiveness() {
-        mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf;
+        mInteractive = mStatusBarState == StatusBarState.KEYGUARD && mHasItemsInStableShelf
+                && !mDark;
         setClickable(mInteractive);
         setFocusable(mInteractive);
         setImportantForAccessibility(mInteractive ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
@@ -602,6 +598,11 @@
     }
 
     @Override
+    public boolean hasOverlappingRendering() {
+        return false;  // Shelf only uses alpha for transitions where the difference can't be seen.
+    }
+
+    @Override
     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
             int oldTop, int oldRight, int oldBottom) {
         updateRelativeOffset();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index b9c8a78..92bfae9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -27,6 +27,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -46,6 +47,7 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 
 import java.text.NumberFormat;
@@ -99,7 +101,6 @@
     private int mDensity;
     private float mIconScale = 1.0f;
     private final Paint mDotPaint = new Paint();
-    private boolean mDotVisible;
     private float mDotRadius;
     private int mStaticDotRadius;
     private int mVisibleState = STATE_ICON;
@@ -110,6 +111,8 @@
     private OnVisibilityChangedListener mOnVisibilityChangedListener;
     private int mDrawableColor;
     private int mIconColor;
+    private int mDecorColor;
+    private float mDarkAmount;
     private ValueAnimator mColorAnimator;
     private int mCurrentSetColor = NO_COLOR;
     private int mAnimationStartColor = NO_COLOR;
@@ -119,6 +122,7 @@
                 animation.getAnimatedFraction());
         setColorInternal(newColor);
     };
+    private final NotificationIconDozeHelper mDozer;
 
     public StatusBarIconView(Context context, String slot, Notification notification) {
         this(context, slot, notification, false);
@@ -127,6 +131,7 @@
     public StatusBarIconView(Context context, String slot, Notification notification,
             boolean blocked) {
         super(context);
+        mDozer = new NotificationIconDozeHelper(context);
         mBlocked = blocked;
         mSlot = slot;
         mNumberPain = new Paint();
@@ -190,6 +195,7 @@
 
     public StatusBarIconView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mDozer = new NotificationIconDozeHelper(context);
         mBlocked = false;
         mAlwaysScaleIcon = true;
         updateIconScale();
@@ -466,7 +472,19 @@
      * to the drawable.
      */
     public void setDecorColor(int iconTint) {
-        mDotPaint.setColor(iconTint);
+        mDecorColor = iconTint;
+        updateDecorColor();
+    }
+
+    private void updateDecorColor() {
+        int color = NotificationUtils.interpolateColors(mDecorColor, Color.WHITE, mDarkAmount);
+        if (mDotPaint.getColor() != color) {
+            mDotPaint.setColor(color);
+
+            if (mDotAppearAmount != 0) {
+                invalidate();
+            }
+        }
     }
 
     /**
@@ -477,6 +495,7 @@
         mDrawableColor = color;
         setColorInternal(color);
         mIconColor = color;
+        mDozer.setColor(color);
     }
 
     private void setColorInternal(int color) {
@@ -649,6 +668,14 @@
         mOnVisibilityChangedListener = listener;
     }
 
+    public void setDark(boolean dark, boolean fade, long delay) {
+        mDozer.setImageDark(this, dark, fade, delay, mIconColor == NO_COLOR);
+        mDozer.setIntensityDark(f -> {
+            mDarkAmount = f;
+            updateDecorColor();
+        }, dark, fade, delay);
+    }
+
     public interface OnVisibilityChangedListener {
         void onVisibilityChanged(int newVisibility);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 3efa29f..bca4b43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -18,7 +18,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
+import android.content.Context;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Paint;
 import android.view.View;
@@ -38,8 +38,8 @@
     private boolean mIsLegacy;
     private int mLegacyColor;
 
-    protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
-        super(view, row);
+    protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+        super(ctx, view, row);
         mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
         mLegacyColor = row.getContext().getColor(R.color.notification_legacy_background_color);
     }
@@ -67,13 +67,11 @@
     }
 
     protected void fadeGrayscale(final boolean dark, long delay) {
-        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                updateGrayscaleMatrix((float) animation.getAnimatedValue());
-                mGreyPaint.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
-                mView.setLayerPaint(mGreyPaint);
-            }
+        getDozer().startIntensityAnimation(animation -> {
+            getDozer().updateGrayscaleMatrix((float) animation.getAnimatedValue());
+            mGreyPaint.setColorFilter(
+                    new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
+            mView.setLayerPaint(mGreyPaint);
         }, dark, delay, new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -86,9 +84,9 @@
 
     protected void updateGrayscale(boolean dark) {
         if (dark) {
-            updateGrayscaleMatrix(1f);
+            getDozer().updateGrayscaleMatrix(1f);
             mGreyPaint.setColorFilter(
-                    new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+                    new ColorMatrixColorFilter(getDozer().getGrayscaleColorMatrix()));
             mView.setLayerPaint(mGreyPaint);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
new file mode 100644
index 0000000..d592c5f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.widget.ImageView;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+
+import java.util.function.Consumer;
+
+public class NotificationDozeHelper {
+    private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
+
+    public void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
+        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                updateGrayscaleMatrix((float) animation.getAnimatedValue());
+                target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+            }
+        }, dark, delay, new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!dark) {
+                    target.setColorFilter(null);
+                }
+            }
+        });
+    }
+
+    public void updateGrayscale(ImageView target, boolean dark) {
+        if (dark) {
+            updateGrayscaleMatrix(1f);
+            target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+        } else {
+            target.setColorFilter(null);
+        }
+    }
+
+    public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
+            boolean dark, long delay, Animator.AnimatorListener listener) {
+        float startIntensity = dark ? 0f : 1f;
+        float endIntensity = dark ? 1f : 0f;
+        ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
+        animator.addUpdateListener(updateListener);
+        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+        animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+        animator.setStartDelay(delay);
+        if (listener != null) {
+            animator.addListener(listener);
+        }
+        animator.start();
+    }
+
+    public void setIntensityDark(Consumer<Float> listener, boolean dark,
+            boolean animate, long delay) {
+        if (animate) {
+            startIntensityAnimation(a -> listener.accept((Float) a.getAnimatedValue()), dark, delay,
+                    null /* listener */);
+        } else {
+            listener.accept(dark ? 1f : 0f);
+        }
+    }
+
+    public void updateGrayscaleMatrix(float intensity) {
+        mGrayscaleColorMatrix.setSaturation(1 - intensity);
+    }
+
+    public ColorMatrix getGrayscaleColorMatrix() {
+        return mGrayscaleColorMatrix;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 38e4ec1..1ffc944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -16,17 +16,10 @@
 
 package com.android.systemui.statusbar.notification;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
 import android.app.Notification;
 import android.content.Context;
-import android.graphics.Color;
 import android.graphics.ColorFilter;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Drawable;
 import android.util.ArraySet;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -37,7 +30,6 @@
 import android.widget.TextView;
 
 import com.android.systemui.Interpolators;
-import com.android.systemui.R;
 import com.android.systemui.ViewInvertHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
@@ -55,10 +47,6 @@
 
     private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
             = new PathInterpolator(0.4f, 0f, 0.7f, 1f);
-    private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
-            0, PorterDuff.Mode.SRC_ATOP);
-    private final int mIconDarkAlpha;
-    private final int mIconDarkColor = 0xffffffff;
 
     protected final ViewInvertHelper mInvertHelper;
     protected final ViewTransformationHelper mTransformationHelper;
@@ -74,8 +62,7 @@
     private boolean mTransformLowPriorityTitle;
 
     protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
-        super(view, row);
-        mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+        super(ctx, view, row);
         mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION);
         mTransformationHelper = new ViewTransformationHelper();
 
@@ -108,6 +95,16 @@
         updateInvertHelper();
     }
 
+    @Override
+    protected NotificationDozeHelper createDozer(Context ctx) {
+        return new NotificationIconDozeHelper(ctx);
+    }
+
+    @Override
+    protected NotificationIconDozeHelper getDozer() {
+        return (NotificationIconDozeHelper) super.getDozer();
+    }
+
     protected void resolveHeaderViews() {
         mIcon = (ImageView) mView.findViewById(com.android.internal.R.id.icon);
         mHeaderText = (TextView) mView.findViewById(com.android.internal.R.id.header_text);
@@ -116,6 +113,7 @@
         mColor = resolveColor(mExpandButton);
         mNotificationHeader = (NotificationHeaderView) mView.findViewById(
                 com.android.internal.R.id.notification_header);
+        getDozer().setColor(mColor);
     }
 
     private int resolveColor(ImageView icon) {
@@ -223,90 +221,8 @@
             // It also may lead to bugs where the icon isn't correctly greyed out.
             boolean hadColorFilter = mNotificationHeader.getOriginalIconColor()
                     != NotificationHeaderView.NO_COLOR;
-            if (fade) {
-                if (hadColorFilter) {
-                    fadeIconColorFilter(mIcon, dark, delay);
-                    fadeIconAlpha(mIcon, dark, delay);
-                } else {
-                    fadeGrayscale(mIcon, dark, delay);
-                }
-            } else {
-                if (hadColorFilter) {
-                    updateIconColorFilter(mIcon, dark);
-                    updateIconAlpha(mIcon, dark);
-                } else {
-                    updateGrayscale(mIcon, dark);
-                }
-            }
-        }
-    }
 
-    private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
-        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                updateIconColorFilter(target, (Float) animation.getAnimatedValue());
-            }
-        }, dark, delay, null /* listener */);
-    }
-
-    private void fadeIconAlpha(final ImageView target, boolean dark, long delay) {
-        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                float t = (float) animation.getAnimatedValue();
-                target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t));
-            }
-        }, dark, delay, null /* listener */);
-    }
-
-    protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
-        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                updateGrayscaleMatrix((float) animation.getAnimatedValue());
-                target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
-            }
-        }, dark, delay, new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (!dark) {
-                    target.setColorFilter(null);
-                }
-            }
-        });
-    }
-
-    private void updateIconColorFilter(ImageView target, boolean dark) {
-        updateIconColorFilter(target, dark ? 1f : 0f);
-    }
-
-    private void updateIconColorFilter(ImageView target, float intensity) {
-        int color = interpolateColor(mColor, mIconDarkColor, intensity);
-        mIconColorFilter.setColor(color);
-        Drawable iconDrawable = target.getDrawable();
-
-        // Also, the notification might have been modified during the animation, so background
-        // might be null here.
-        if (iconDrawable != null) {
-            Drawable d = iconDrawable.mutate();
-            // DrawableContainer ignores the color filter if it's already set, so clear it first to
-            // get it set and invalidated properly.
-            d.setColorFilter(null);
-            d.setColorFilter(mIconColorFilter);
-        }
-    }
-
-    private void updateIconAlpha(ImageView target, boolean dark) {
-        target.setImageAlpha(dark ? mIconDarkAlpha : 255);
-    }
-
-    protected void updateGrayscale(ImageView target, boolean dark) {
-        if (dark) {
-            updateGrayscaleMatrix(1f);
-            target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
-        } else {
-            target.setColorFilter(null);
+            getDozer().setImageDark(mIcon, dark, fade, delay, !hadColorFilter);
         }
     }
 
@@ -316,22 +232,6 @@
         mNotificationHeader.setOnClickListener(expandable ? onClickListener : null);
     }
 
-    private static int interpolateColor(int source, int target, float t) {
-        int aSource = Color.alpha(source);
-        int rSource = Color.red(source);
-        int gSource = Color.green(source);
-        int bSource = Color.blue(source);
-        int aTarget = Color.alpha(target);
-        int rTarget = Color.red(target);
-        int gTarget = Color.green(target);
-        int bTarget = Color.blue(target);
-        return Color.argb(
-                (int) (aSource * (1f - t) + aTarget * t),
-                (int) (rSource * (1f - t) + rTarget * t),
-                (int) (gSource * (1f - t) + gTarget * t),
-                (int) (bSource * (1f - t) + bTarget * t));
-    }
-
     @Override
     public NotificationHeaderView getNotificationHeader() {
         return mNotificationHeader;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java
new file mode 100644
index 0000000..9f79ef2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+public class NotificationIconDozeHelper extends NotificationDozeHelper {
+
+    private final int mImageDarkAlpha;
+    private final int mImageDarkColor = 0xffffffff;
+    private final PorterDuffColorFilter mImageColorFilter = new PorterDuffColorFilter(
+            0, PorterDuff.Mode.SRC_ATOP);
+
+    private int mColor = Color.BLACK;
+
+    public NotificationIconDozeHelper(Context ctx) {
+        mImageDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+    }
+
+    public void setColor(int color) {
+        mColor = color;
+    }
+
+    public void setImageDark(ImageView target, boolean dark, boolean fade, long delay,
+            boolean useGrayscale) {
+        if (fade) {
+            if (!useGrayscale) {
+                fadeImageColorFilter(target, dark, delay);
+                fadeImageAlpha(target, dark, delay);
+            } else {
+                fadeGrayscale(target, dark, delay);
+            }
+        } else {
+            if (!useGrayscale) {
+                updateImageColorFilter(target, dark);
+                updateImageAlpha(target, dark);
+            } else {
+                updateGrayscale(target, dark);
+            }
+        }
+    }
+
+    private void fadeImageColorFilter(final ImageView target, boolean dark, long delay) {
+        startIntensityAnimation(animation -> {
+            updateImageColorFilter(target, (Float) animation.getAnimatedValue());
+        }, dark, delay, null /* listener */);
+    }
+
+    private void fadeImageAlpha(final ImageView target, boolean dark, long delay) {
+        startIntensityAnimation(animation -> {
+            float t = (float) animation.getAnimatedValue();
+            target.setImageAlpha((int) (255 * (1f - t) + mImageDarkAlpha * t));
+        }, dark, delay, null /* listener */);
+    }
+
+    private void updateImageColorFilter(ImageView target, boolean dark) {
+        updateImageColorFilter(target, dark ? 1f : 0f);
+    }
+
+    private void updateImageColorFilter(ImageView target, float intensity) {
+        int color = NotificationUtils.interpolateColors(mColor, mImageDarkColor, intensity);
+        mImageColorFilter.setColor(color);
+        Drawable imageDrawable = target.getDrawable();
+
+        // Also, the notification might have been modified during the animation, so background
+        // might be null here.
+        if (imageDrawable != null) {
+            Drawable d = imageDrawable.mutate();
+            // DrawableContainer ignores the color filter if it's already set, so clear it first to
+            // get it set and invalidated properly.
+            d.setColorFilter(null);
+            d.setColorFilter(mImageColorFilter);
+        }
+    }
+
+    private void updateImageAlpha(ImageView target, boolean dark) {
+        target.setImageAlpha(dark ? mImageDarkAlpha : 255);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 846d03a..f0b6b2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.notification;
 
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Color;
 import android.service.notification.StatusBarNotification;
@@ -46,7 +45,8 @@
     private int mContentHeight;
     private int mMinHeightHint;
 
-    protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
+    protected NotificationTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
         super(ctx, view, row);
         mTransformationHelper.setCustomTransformation(
                 new ViewTransformationHelper.CustomTransformation() {
@@ -154,16 +154,20 @@
         // This also clears the existing types
         super.updateTransformedTypes();
         if (mTitle != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE, mTitle);
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
+                    mTitle);
         }
         if (mText != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT, mText);
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+                    mText);
         }
         if (mPicture != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE, mPicture);
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_IMAGE,
+                    mPicture);
         }
         if (mProgressBar != null) {
-            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS, mProgressBar);
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_PROGRESS,
+                    mProgressBar);
         }
     }
 
@@ -173,7 +177,7 @@
             return;
         }
         super.setDark(dark, fade, delay);
-        setPictureGrayscale(dark, fade, delay);
+        setPictureDark(dark, fade, delay);
         setProgressBarDark(dark, fade, delay);
     }
 
@@ -188,12 +192,9 @@
     }
 
     private void fadeProgressDark(final ProgressBar target, final boolean dark, long delay) {
-        startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                float t = (float) animation.getAnimatedValue();
-                updateProgressDark(target, t);
-            }
+        getDozer().startIntensityAnimation(animation -> {
+            float t = (float) animation.getAnimatedValue();
+            updateProgressDark(target, t);
         }, dark, delay, null /* listener */);
     }
 
@@ -207,13 +208,9 @@
         updateProgressDark(target, dark ? 1f : 0f);
     }
 
-    protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) {
+    private void setPictureDark(boolean dark, boolean fade, long delay) {
         if (mPicture != null) {
-            if (fade) {
-                fadeGrayscale(mPicture, grayscale, delay);
-            } else {
-                updateGrayscale(mPicture, grayscale);
-            }
+            getDozer().setImageDark(mPicture, dark, fade, delay, true /* useGrayscale */);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index c85e8d8..f4db9a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -16,24 +16,17 @@
 
 package com.android.systemui.statusbar.notification;
 
-import android.animation.Animator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Color;
-import android.graphics.ColorMatrix;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
 import android.support.v4.graphics.ColorUtils;
 import android.view.NotificationHeaderView;
 import android.view.View;
 
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
 
 /**
  * Wraps the actual notification content view; used to implement behaviors which are different for
@@ -41,14 +34,14 @@
  */
 public abstract class NotificationViewWrapper implements TransformableView {
 
-    protected final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
     protected final View mView;
     protected final ExpandableNotificationRow mRow;
+    private final NotificationDozeHelper mDozer;
+
     protected boolean mDark;
     private int mBackgroundColor = 0;
     protected boolean mShouldInvertDark;
     protected boolean mDarkInitialized = false;
-    private boolean mForcedInvisible;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -65,13 +58,22 @@
         } else if (v instanceof NotificationHeaderView) {
             return new NotificationHeaderViewWrapper(ctx, v, row);
         } else {
-            return new NotificationCustomViewWrapper(v, row);
+            return new NotificationCustomViewWrapper(ctx, v, row);
         }
     }
 
-    protected NotificationViewWrapper(View view, ExpandableNotificationRow row) {
+    protected NotificationViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
         mView = view;
         mRow = row;
+        mDozer = createDozer(ctx);
+    }
+
+    protected NotificationDozeHelper createDozer(Context ctx) {
+        return new NotificationDozeHelper();
+    }
+
+    protected NotificationDozeHelper getDozer() {
+        return mDozer;
     }
 
     /**
@@ -112,26 +114,6 @@
                 || ColorUtils.calculateLuminance(backgroundColor) > 0.5;
     }
 
-
-    protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
-            boolean dark, long delay, Animator.AnimatorListener listener) {
-        float startIntensity = dark ? 0f : 1f;
-        float endIntensity = dark ? 1f : 0f;
-        ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
-        animator.addUpdateListener(updateListener);
-        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
-        animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-        animator.setStartDelay(delay);
-        if (listener != null) {
-            animator.addListener(listener);
-        }
-        animator.start();
-    }
-
-    protected void updateGrayscaleMatrix(float intensity) {
-        mGrayscaleColorMatrix.setSaturation(1 - intensity);
-    }
-
     /**
      * Update the appearance of the expand button.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 3706dc8..dee15d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -95,7 +95,7 @@
     private int mActualLayoutWidth = NO_VALUE;
     private float mActualPaddingEnd = NO_VALUE;
     private float mActualPaddingStart = NO_VALUE;
-    private boolean mCentered;
+    private boolean mDark;
     private boolean mChangingViewPositions;
     private int mAddAnimationStartIndex = -1;
     private int mCannedAnimationStartIndex = -1;
@@ -183,6 +183,9 @@
                 mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
             }
         }
+        if (mDark && child instanceof StatusBarIconView) {
+            ((StatusBarIconView) child).setDark(mDark, false, 0);
+        }
     }
 
     @Override
@@ -312,7 +315,8 @@
                 numDots++;
             }
         }
-        if (mCentered && translationX < getLayoutEnd()) {
+        boolean center = mDark;
+        if (center && translationX < getLayoutEnd()) {
             float delta = (getLayoutEnd() - translationX) / 2;
             for (int i = 0; i < childCount; i++) {
                 View view = getChildAt(i);
@@ -390,9 +394,15 @@
         mChangingViewPositions = changingViewPositions;
     }
 
-    public void setAmbient(boolean ambient) {
-        mCentered = ambient;
+    public void setDark(boolean dark, boolean fade, long delay) {
+        mDark = dark;
         mDisallowNextAnimation = true;
+        for (int i = 0; i < getChildCount(); i++) {
+            View view = getChildAt(i);
+            if (view instanceof StatusBarIconView) {
+                ((StatusBarIconView) view).setDark(dark, fade, delay);
+            }
+        }
     }
 
     public IconState getIconState(StatusBarIconView icon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c24a2a0..307a8c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2472,4 +2472,8 @@
     public void setNoVisibleNotifications(boolean noNotifications) {
         mNoVisibleNotifications = noNotifications;
     }
+
+    public void setPulsing(boolean pulsing) {
+        mKeyguardStatusView.setPulsing(pulsing);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9a71ed7..472af65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -89,7 +89,6 @@
 import android.provider.Settings;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
-import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -242,7 +241,6 @@
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.SystemUI;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.statusbar.policy.RemoteInputView;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -5012,19 +5010,25 @@
                 @Override
                 public void onPulseStarted() {
                     callback.onPulseStarted();
-                    if (!mHeadsUpManager.getAllEntries().isEmpty()) {
+                    Collection<HeadsUpManager.HeadsUpEntry> pulsingEntries =
+                            mHeadsUpManager.getAllEntries();
+                    if (!pulsingEntries.isEmpty()) {
                         // Only pulse the stack scroller if there's actually something to show.
                         // Otherwise just show the always-on screen.
-                        mStackScroller.setPulsing(true);
-                        mVisualStabilityManager.setPulsing(true);
+                        setPulsing(pulsingEntries);
                     }
                 }
 
                 @Override
                 public void onPulseFinished() {
                     callback.onPulseFinished();
-                    mStackScroller.setPulsing(false);
-                    mVisualStabilityManager.setPulsing(false);
+                    setPulsing(null);
+                }
+
+                private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+                    mStackScroller.setPulsing(pulsing);
+                    mNotificationPanel.setPulsing(pulsing != null);
+                    mVisualStabilityManager.setPulsing(pulsing != null);
                 }
             }, reason);
         }
@@ -5767,12 +5771,16 @@
                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
             final String pkg = sbn.getPackageName();
             NotificationInfo info = (NotificationInfo) gutsView;
-            final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
-                    NotificationChannel channel, int appUid) -> {
-                mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
-                guts.resetFalsingCheck();
-                startAppNotificationSettingsActivity(pkg, appUid, channel);
-            };
+            // Settings link is only valid for notifications that specify a user, unless this is the
+            // system user.
+            NotificationInfo.OnSettingsClickListener onSettingsClick = null;
+            if (!userHandle.equals(UserHandle.ALL) || mCurrentUserId == UserHandle.USER_SYSTEM) {
+                onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
+                    mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
+                    guts.resetFalsingCheck();
+                    startAppNotificationSettingsActivity(pkg, appUid, channel);
+                };
+            }
             final View.OnClickListener onDoneClick = (View v) -> {
                 saveAndCloseNotificationMenu(info, row, guts, v);
             };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index fe83dc4..b2b23a55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -59,6 +59,7 @@
     private boolean mPanelTracking;
     private boolean mExpansionChanging;
     private boolean mPanelFullWidth;
+    private boolean mPulsing;
 
     public AmbientState(Context context) {
         reload(context);
@@ -285,6 +286,14 @@
         mPanelTracking = panelTracking;
     }
 
+    public boolean isPulsing() {
+        return mPulsing;
+    }
+
+    public void setPulsing(boolean pulsing) {
+        mPulsing = pulsing;
+    }
+
     public boolean isPanelTracking() {
         return mPanelTracking;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7d2d0df..15fcb38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -72,6 +72,7 @@
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationGuts;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StackScrollerDecorView;
@@ -86,6 +87,7 @@
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -331,7 +333,7 @@
         }
     };
     private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
-    private boolean mPulsing;
+    private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
     private boolean mDrawBackgroundAsSrc;
     private boolean mFadingOut;
     private boolean mParentNotFullyVisible;
@@ -1917,15 +1919,19 @@
         int numShownItems = 0;
         boolean finish = false;
         int maxDisplayedNotifications = mAmbientState.isDark()
-                ? (mPulsing ? 1 : 0)
+                ? (isPulsing() ? 1 : 0)
                 : mMaxDisplayedNotifications;
 
         for (int i = 0; i < getChildCount(); i++) {
             ExpandableView expandableView = (ExpandableView) getChildAt(i);
             if (expandableView.getVisibility() != View.GONE
                     && !expandableView.hasNoContentHeight()) {
-                if (maxDisplayedNotifications != -1
-                        && numShownItems >= maxDisplayedNotifications) {
+                boolean limitReached = maxDisplayedNotifications != -1
+                        && numShownItems >= maxDisplayedNotifications;
+                boolean notificationOnAmbientThatIsNotPulsing = isPulsing()
+                        && expandableView instanceof ExpandableNotificationRow
+                        && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
+                if (limitReached || notificationOnAmbientThatIsNotPulsing) {
                     expandableView = mShelf;
                     finish = true;
                 }
@@ -1971,6 +1977,19 @@
         mAmbientState.setLayoutMaxHeight(mContentHeight);
     }
 
+    private boolean isPulsing(NotificationData.Entry entry) {
+        for (HeadsUpManager.HeadsUpEntry e : mPulsing) {
+            if (e.entry == entry) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isPulsing() {
+        return mPulsing != null;
+    }
+
     private void updateScrollability() {
         boolean scrollable = getScrollRange() > 0;
         if (scrollable != mScrollable) {
@@ -2784,7 +2803,7 @@
     }
 
     private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled || mPulsing;
+        boolean running = mAnimationsEnabled || isPulsing();
         mShelf.setAnimationsEnabled(running);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2795,7 +2814,7 @@
     }
 
     private void updateAnimationState(View child) {
-        updateAnimationState((mAnimationsEnabled || mPulsing)
+        updateAnimationState((mAnimationsEnabled || isPulsing())
                 && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
@@ -4055,14 +4074,16 @@
         return mIsExpanded;
     }
 
-    public void setPulsing(boolean pulsing) {
-        if (mPulsing == pulsing) {
+    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+        if (mPulsing == null && pulsing == null) {
             return;
         }
         mPulsing = pulsing;
+        mAmbientState.setPulsing(isPulsing());
         updateNotificationAnimationStates();
         updateContentHeight();
         notifyHeightChangeListener(mShelf);
+        requestChildrenUpdate();
     }
 
     public void setFadingOut(boolean fadingOut) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index c67cccc..8609eeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -100,4 +100,10 @@
         ViewUtils.detachView(mQsDetail);
         mTestableLooper.processAllMessages();
     }
+
+    @Test
+    public void testNullAdapterClick() {
+        mQsDetail.setupDetailFooter(mock(DetailAdapter.class));
+        mQsDetail.findViewById(android.R.id.button2).performClick();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 21930a3..0621f4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -206,6 +206,29 @@
     }
 
     @Test
+    public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                null, null, null, null);
+        final TextView settingsButton =
+                (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+        assertTrue(settingsButton.getVisibility() != View.VISIBLE);
+    }
+
+    @Test
+    public void testBindNotification_SettingsButtonReappersAfterSecondBind() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                null, null, null, null);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                (View v, NotificationChannel c, int appUid) -> {}, null, null, null);
+        final TextView settingsButton =
+                (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+        assertEquals(View.VISIBLE, settingsButton.getVisibility());
+    }
+
+    @Test
     public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 31b9bae..efb9fea4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -44,4 +44,11 @@
         ViewUtils.detachView(row.getMenuView());
         TestableLooper.get(this).processAllMessages();
     }
+
+    @Test
+    public void testRecreateMenu() {
+        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        row.createMenu(null);
+        row.createMenu(null);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
new file mode 100644
index 0000000..a69de7a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class NotificationViewWrapperTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+    }
+
+    @Test
+    public void constructor_doesntUseViewContext() throws Exception {
+        new TestableNotificationViewWrapper(mContext, new View(null /* context */), null /* row */);
+    }
+
+    static class TestableNotificationViewWrapper extends NotificationViewWrapper {
+        protected TestableNotificationViewWrapper(Context ctx, View view,
+                ExpandableNotificationRow row) {
+            super(ctx, view, row);
+        }
+    }
+}
\ No newline at end of file
diff --git a/preloaded-classes b/preloaded-classes
index a72a042..892c593 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1817,7 +1817,6 @@
 android.text.FontConfig$Family$1
 android.text.FontConfig$Font
 android.text.FontConfig$Font$1
-android.text.FontManager
 android.text.GetChars
 android.text.GraphicsOperations
 android.text.Html
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index f6d91f4..c4a2831 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -165,6 +165,14 @@
     // Package: android
     NOTE_NET_LIMIT_SNOOZED = 36;
 
+    // Inform the user they need to sign in to an account
+    // Package: android, and others
+    NOTE_ACCOUNT_REQUIRE_SIGNIN = 37;
+
+    // Inform the user that there has been a permission request for an account
+    // Package: android
+    NOTE_ACCOUNT_CREDENTIAL_PERMISSION = 38;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
@@ -216,9 +224,5 @@
     // Notify the user that data or apps are being moved to external storage.
     // Package: com.android.systemui
     NOTE_STORAGE_MOVE = 0x534d4f56;
-
-    // Account Manager allocates IDs sequentially, starting here.
-    // Package: android
-    ACCOUNT_MANAGER_BASE = 0x70000000;
   }
 }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index c532efb..0acbb02 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1282,7 +1282,9 @@
 
     ANativeWindow *anw = nullptr;
     if (sur != 0) {
+        // Connect the native window handle to buffer queue.
         anw = ANativeWindow_fromSurface(_env, sur);
+        native_window_api_connect(anw, NATIVE_WINDOW_API_CPU);
     }
 
     rsAllocationSetSurface((RsContext)con, (RsAllocation)alloc, anw);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 087c248..1968d2e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -585,17 +585,12 @@
             result = mEnabledServicesForFeedbackTempList;
             result.clear();
             List<Service> services = userState.mBoundServices;
-            while (feedbackType != 0) {
-                final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
-                feedbackType &= ~feedbackTypeBit;
-                final int serviceCount = services.size();
-                for (int i = 0; i < serviceCount; i++) {
-                    Service service = services.get(i);
-                    // Don't report the UIAutomation (fake service)
-                    if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
-                            && (service.mFeedbackType & feedbackTypeBit) != 0) {
-                        result.add(service.mAccessibilityServiceInfo);
-                    }
+            for (int serviceCount = services.size(), i = 0; i < serviceCount; ++i) {
+                Service service = services.get(i);
+                // Don't report the UIAutomation (fake service)
+                if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
+                        && (service.mFeedbackType & feedbackType) != 0) {
+                    result.add(service.mAccessibilityServiceInfo);
                 }
             }
         }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 0482e73..ac81565 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1631,7 +1631,7 @@
 
     @Override
     public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
-            int profileId) {
+            int profileId, String packageName) {
         final int userId = UserHandle.getCallingUserId();
 
         if (DEBUG) {
@@ -1653,8 +1653,11 @@
                 Provider provider = mProviders.get(i);
                 AppWidgetProviderInfo info = provider.info;
 
-                // Ignore an invalid provider or one not matching the filter.
-                if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
+                // Ignore an invalid provider, one not matching the filter,
+                // or one that isn't in the given package, if any.
+                boolean inPackage = packageName == null
+                        || provider.id.componentName.getPackageName().equals(packageName);
+                if (provider.zombie || (info.widgetCategory & categoryFilter) == 0 || !inPackage) {
                     continue;
                 }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index be14440..502b5fc 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -23,7 +23,6 @@
 import static com.android.server.autofill.Helper.VERBOSE;
 import static com.android.server.autofill.Helper.bundleToString;
 
-import android.Manifest;
 import android.annotation.NonNull;
 import android.app.ActivityManagerInternal;
 import android.content.BroadcastReceiver;
@@ -36,7 +35,6 @@
 import android.database.ContentObserver;
 import android.graphics.Rect;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 3d1c251..15ec98f 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -57,6 +57,7 @@
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutoFillManagerClient;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.IResultReceiver;
@@ -290,7 +291,8 @@
                 + " f=" + flags;
         mRequestsHistory.log(historyItem);
 
-        // TODO(b/33197203): Handle partitioning
+        // TODO(b/33197203): Handle scenario when user forced autofill after app was already
+        // autofilled.
         final Session session = mSessions.get(activityToken);
         if (session != null) {
             // Already started...
@@ -430,8 +432,11 @@
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
 
+        pw.print(prefix); pw.print("User :"); pw.println(mUserId);
         pw.print(prefix); pw.print("Component:"); pw.println(mInfo != null
                 ? mInfo.getServiceInfo().getComponentName() : null);
+        pw.print(prefix); pw.print("Default component: ");
+            pw.println(mContext.getString(R.string.config_defaultAutofillService));
         pw.print(prefix); pw.print("Disabled:"); pw.println(mDisabled);
 
         if (VERBOSE && mInfo != null) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index ac7d19e..801769c 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -48,6 +48,7 @@
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
 import android.util.ArrayMap;
+import android.util.DebugUtils;
 import android.util.Slog;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
@@ -112,20 +113,19 @@
     @GuardedBy("mLock")
     RemoteFillService mRemoteFillService;
 
-    // TODO(b/33197203 , b/35707731): Use List once it supports partitioning
     @GuardedBy("mLock")
-    private FillResponse mCurrentResponse;
+    private ArrayList<FillResponse> mResponses;
 
     /**
-     * Used to remember which {@link Dataset} filled the session.
+     * Response that requires a service authentitcation request.
      */
-    // TODO(b/33197203 , b/35707731): will be removed once it supports partitioning
     @GuardedBy("mLock")
-    private Dataset mAutoFilledDataset;
+    private FillResponse mResponseWaitingAuth;
 
     /**
      * Dataset that when tapped launched a service authentication request.
      */
+    @GuardedBy("mLock")
     private Dataset mDatasetWaitingAuth;
 
     /**
@@ -163,8 +163,8 @@
         mClient = IAutoFillManagerClient.Stub.asInterface(client);
         try {
             client.linkToDeath(() -> {
-                if (DEBUG) {
-                    Slog.d(TAG, "app binder died");
+                if (VERBOSE) {
+                    Slog.v(TAG, "app binder died");
                 }
 
                 removeSelf();
@@ -193,6 +193,10 @@
             notifyUnavailableToClient();
         }
         synchronized (mLock) {
+            if (response.getAuthentication() != null) {
+                // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
+                mResponseWaitingAuth = response;
+            }
             processResponseLocked(response);
         }
 
@@ -318,23 +322,27 @@
     }
 
     public void setAuthenticationResultLocked(Bundle data) {
-        if (mCurrentResponse == null || data == null) {
+        if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) {
             removeSelf();
         } else {
             final Parcelable result = data.getParcelable(
                     AutofillManager.EXTRA_AUTHENTICATION_RESULT);
             if (result instanceof FillResponse) {
                 mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
-
-                mCurrentResponse = (FillResponse) result;
-                processResponseLocked(mCurrentResponse);
+                mResponseWaitingAuth = null;
+                processResponseLocked((FillResponse) result);
             } else if (result instanceof Dataset) {
                 final Dataset dataset = (Dataset) result;
-                final int index = mCurrentResponse.getDatasets().indexOf(mDatasetWaitingAuth);
-                if (index >= 0) {
-                    mCurrentResponse.getDatasets().set(index, dataset);
-                    autoFill(dataset);
-                    mDatasetWaitingAuth = null;
+                for (int i = 0; i < mResponses.size(); i++) {
+                    final FillResponse response = mResponses.get(i);
+                    final int index = response.getDatasets().indexOf(mDatasetWaitingAuth);
+                    if (index >= 0) {
+                        response.getDatasets().set(index, dataset);
+                        mDatasetWaitingAuth = null;
+                        autoFill(dataset);
+                        resetViewStatesLocked(dataset, ViewState.STATE_WAITING_DATASET_AUTH);
+                        return;
+                    }
                 }
             }
         }
@@ -354,15 +362,19 @@
             Slog.wtf(TAG, "showSaveLocked(): no mStructure");
             return true;
         }
-        if (mCurrentResponse == null) {
+        if (mResponses == null) {
             // Happens when the activity / session was finished before the service replied, or
             // when the service cannot autofill it (and returned a null response).
             if (DEBUG) {
-                Slog.d(TAG, "showSaveLocked(): no mCurrentResponse");
+                Slog.d(TAG, "showSaveLocked(): no responses on session");
             }
             return true;
         }
-        final SaveInfo saveInfo = mCurrentResponse.getSaveInfo();
+
+        // TODO(b/33197203 , b/35707731): must iterate over all responses
+        final FillResponse response = mResponses.get(0);
+
+        final SaveInfo saveInfo = response.getSaveInfo();
         if (DEBUG) {
             Slog.d(TAG, "showSaveLocked(): saveInfo=" + saveInfo);
         }
@@ -385,7 +397,6 @@
             return true;
         }
 
-        // TODO(b/33197203 , b/35707731): refactor excessive calls to getCurrentValue()
         boolean allRequiredAreNotEmpty = true;
         boolean atLeastOneChanged = false;
         for (int i = 0; i < requiredIds.length; i++) {
@@ -393,7 +404,8 @@
             final ViewState viewState = mViewStates.get(id);
             if (viewState == null) {
                 Slog.w(TAG, "showSaveLocked(): no ViewState for required " + id);
-                continue;
+                allRequiredAreNotEmpty = false;
+                break;
             }
 
             final AutofillValue currentValue = viewState.getCurrentValue();
@@ -462,7 +474,8 @@
             Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
         }
 
-        final Bundle extras = this.mCurrentResponse.getExtras();
+        // TODO(b/33197203 , b/35707731): decide how to handle bundle in multiple partitions
+        final Bundle extras = mResponses != null ? mResponses.get(0).getExtras() : null;
 
         for (Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) {
             final AutofillValue value = entry.getValue().getCurrentValue();
@@ -497,16 +510,21 @@
     }
 
     void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
-        if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) {
-            // TODO(b/33197203): ignoring because we don't support partitions yet
-            Slog.d(TAG, "updateLocked(): ignoring " + id + " after app was autofilled");
-            return;
-        }
-
         ViewState viewState = mViewStates.get(id);
+
         if (viewState == null) {
-            viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL);
-            mViewStates.put(id, viewState);
+            if ((flags & (FLAG_START_SESSION | FLAG_VALUE_CHANGED)) != 0) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Creating viewState for " + id + " on " + getFlagAsString(flags));
+                }
+                viewState = new ViewState(this, id, this, ViewState.STATE_INITIAL);
+                mViewStates.put(id, viewState);
+            } else if ((flags & FLAG_VIEW_ENTERED) != 0) {
+                viewState = startPartitionLocked(id);
+            } else {
+                if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id);
+                return;
+            }
         }
 
         if ((flags & FLAG_START_SESSION) != 0) {
@@ -530,7 +548,8 @@
                 }
                 // Update the internal state...
                 viewState.setState(ViewState.STATE_CHANGED);
-                // ... and the chooser UI.
+
+                //..and the UI
                 if (value.isText()) {
                     getUiForShowing().filterFillUi(value.getTextValue().toString());
                 } else {
@@ -551,10 +570,6 @@
             // If the ViewState is ready to be displayed, onReady() will be called.
             viewState.update(value, virtualBounds);
 
-            if (mCurrentResponse != null) {
-                viewState.setResponse(mCurrentResponse);
-            }
-
             return;
         }
 
@@ -566,7 +581,28 @@
             return;
         }
 
-        Slog.w(TAG, "updateLocked(): unknown flags " + flags);
+        Slog.w(TAG, "updateLocked(): unknown flags " + flags + ": " + getFlagAsString(flags));
+    }
+
+    private ViewState startPartitionLocked(AutofillId id) {
+        if (DEBUG) {
+            Slog.d(TAG, "Starting partition for view id " + id);
+        }
+        final ViewState viewState =
+                new ViewState(this, id, this,ViewState.STATE_STARTED_PARTITION);
+        mViewStates.put(id, viewState);
+
+        /*
+         * TODO(b/33197203 , b/35707731): when start a new partition, it should
+         *
+         * - add autofilled fields as sanitized
+         * - set focus on ViewStructure that triggered it
+         * - pass the first onFillRequest() bundle
+         * - optional: perhaps add a new flag onFilLRequest() to indicate it's a new partition?
+         */
+        mRemoteFillService.onFillRequest(mStructure, null, 0);
+
+        return viewState;
     }
 
     @Override
@@ -580,6 +616,10 @@
         getUiForShowing().showFillUi(filledId, response, filterText, mPackageName);
     }
 
+    String getFlagAsString(int flag) {
+        return DebugUtils.flagsToString(AutofillManager.class, "FLAG_", flag);
+    }
+
     private void notifyUnavailableToClient() {
         if (mCurrentViewId == null) {
             // TODO(b/33197203): temporary sanity check; should never happen
@@ -597,8 +637,7 @@
 
     private void processResponseLocked(FillResponse response) {
         if (DEBUG) {
-            Slog.d(TAG, "processResponseLocked(auth=" + response.getAuthentication()
-                + "):" + response);
+            Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response);
         }
 
         if (mCurrentViewId == null) {
@@ -607,7 +646,10 @@
             return;
         }
 
-        mCurrentResponse = response;
+        if (mResponses == null) {
+            mResponses = new ArrayList<>(4);
+        }
+        mResponses.add(response);
 
         setViewStatesLocked(response, ViewState.STATE_FILLABLE);
 
@@ -669,10 +711,22 @@
         }
     }
 
+    /**
+     * Resets the given state from all existing views in the given dataset.
+     */
+    private void resetViewStatesLocked(@NonNull Dataset dataset, int state) {
+        final ArrayList<AutofillId> ids = dataset.getFieldIds();
+        for (int j = 0; j < ids.size(); j++) {
+            final AutofillId id = ids.get(j);
+            final ViewState viewState = mViewStates.get(id);
+            if (viewState != null)  {
+                viewState.resetState(state);
+            }
+        }
+    }
+
     void autoFill(Dataset dataset) {
         synchronized (mLock) {
-            mAutoFilledDataset = dataset;
-
             // Autofill it directly...
             if (dataset.getAuthentication() == null) {
                 autoFillApp(dataset);
@@ -680,7 +734,9 @@
             }
 
             // ...or handle authentication.
+            // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
             mDatasetWaitingAuth = dataset;
+            setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH);
             final Intent fillInIntent = createAuthFillInIntent(mStructure, null);
             startAuthentication(dataset.getAuthentication(), fillInIntent);
         }
@@ -690,8 +746,8 @@
         return mService.getServiceName();
     }
 
-    FillResponse getCurrentResponse() {
-        return mCurrentResponse;
+    FillResponse getResponseWaitingAuth() {
+        return mResponseWaitingAuth;
     }
 
     private Intent createAuthFillInIntent(AssistStructure structure, Bundle extras) {
@@ -714,8 +770,8 @@
     void dumpLocked(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("mFlags: "); pw.println(mFlags);
-        pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse);
-        pw.print(prefix); pw.print("mAutoFilledDataset: "); pw.println(mAutoFilledDataset);
+        pw.print(prefix); pw.print("mResponses: "); pw.println(mResponses);
+        pw.print(prefix); pw.print("mResponseWaitingAuth: "); pw.println(mResponseWaitingAuth);
         pw.print(prefix); pw.print("mDatasetWaitingAuth: "); pw.println(mDatasetWaitingAuth);
         pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId);
         pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size());
@@ -811,4 +867,4 @@
         destroyLocked();
         mService.removeSessionLocked(mActivityToken);
     }
-}
\ No newline at end of file
+}
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 3aba723..549f231 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -16,10 +16,13 @@
 
 package com.android.server.autofill;
 
+import static com.android.server.autofill.Helper.DEBUG;
+
 import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.service.autofill.FillResponse;
 import android.util.DebugUtils;
+import android.util.Slog;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
@@ -40,6 +43,8 @@
                 @Nullable AutofillValue value);
     }
 
+    private static final String TAG = "ViewState";
+
     // NOTE: state constants must be public because of flagstoString().
     public static final int STATE_UNKNOWN = 0x00;
     /** Initial state. */
@@ -52,6 +57,10 @@
     public static final int STATE_CHANGED = 0x08;
     /** Set only in the View that started a session. */
     public static final int STATE_STARTED_SESSION = 0x10;
+    /** View that started a new partition when focused on. */
+    public static final int STATE_STARTED_PARTITION = 0x20;
+    /** User select a dataset in this view, but service must authenticate first. */
+    public static final int STATE_WAITING_DATASET_AUTH = 0x40;
 
     public final AutofillId id;
     private final Listener mListener;
@@ -122,9 +131,15 @@
     }
 
     void setState(int state) {
-        // TODO(b/33197203 , b/35707731): currently it's always setting one state, but once it
-        // supports partitioning it will need to 'or' some of them..
-        mState = state;
+        if (mState == STATE_INITIAL) {
+            mState = state;
+        } else {
+            mState |= state;
+        }
+    }
+
+    void resetState(int state) {
+        mState &= ~state;
     }
 
     // TODO(b/33197203): need to refactor / rename / document this method to make it clear that
@@ -147,6 +162,12 @@
      * fill UI is ready to be displayed (i.e. when response and bounds are set).
      */
     void maybeCallOnFillReady() {
+        if ((mState & (STATE_AUTOFILLED | STATE_WAITING_DATASET_AUTH)) != 0) {
+            if (DEBUG) {
+                Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
+            }
+            return;
+        }
         // First try the current response associated with this View.
         if (mResponse != null) {
             if (mResponse.getDatasets() != null) {
@@ -155,9 +176,9 @@
             return;
         }
         // Then checks if the session has a response waiting authentication; if so, uses it instead.
-        final FillResponse currentResponse = mSession.getCurrentResponse();
-        if (currentResponse.getAuthentication() != null) {
-            mListener.onFillReady(currentResponse, this.id, mCurrentValue);
+        final FillResponse responseWaitingAuth = mSession.getResponseWaitingAuth();
+        if (responseWaitingAuth != null) {
+            mListener.onFillReady(responseWaitingAuth, this.id, mCurrentValue);
         }
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d38fb96..b69d1dc 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -101,8 +101,9 @@
             content.measure(widthMeasureSpec, heightMeasureSpec);
             content.setOnClickListener(v -> mCallback.onResponsePicked(response));
             content.setElevation(context.getResources().getDimension(R.dimen.floating_window_z));
-            mContentWidth = content.getMeasuredWidth();
-            mContentHeight = content.getMeasuredHeight();
+            // TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width
+            mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
+            mContentHeight = Math.min(content.getMeasuredHeight(), 500);
 
             mWindow = new AnchoredWindow(content);
             mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 099f557..8003d21 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -39,8 +39,8 @@
 
 LOCAL_JACK_FLAGS := \
  -D jack.transformations.boost-locked-region-priority=true \
- -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService \
- -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection \
- -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection
+ -D jack.transformations.boost-locked-region-priority.classname=com.android.server.am.ActivityManagerService,com.android.server.wm.WindowHashMap \
+ -D jack.transformations.boost-locked-region-priority.request=com.android.server.am.ActivityManagerService\#boostPriorityForLockedSection,com.android.server.wm.WindowManagerService\#boostPriorityForLockedSection \
+ -D jack.transformations.boost-locked-region-priority.reset=com.android.server.am.ActivityManagerService\#resetPriorityAfterLockedSection,com.android.server.wm.WindowManagerService\#resetPriorityAfterLockedSection
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0e752ff..25ac008 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -29,13 +29,6 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_NONE;
-import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
-import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.uidRulesToString;
 
 import android.annotation.Nullable;
 import android.app.BroadcastOptions;
@@ -104,7 +97,6 @@
 import android.security.KeyStore;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
-import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.LocalLog.ReadOnlyLocalLog;
 import android.util.Log;
@@ -130,6 +122,7 @@
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.WakeupMessage;
 import com.android.internal.util.XmlUtils;
+import com.android.server.LocalServices;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.DataConnectionStats;
 import com.android.server.connectivity.KeepaliveTracker;
@@ -147,6 +140,7 @@
 import com.android.server.connectivity.Vpn;
 import com.android.server.net.BaseNetworkObserver;
 import com.android.server.net.LockdownVpnTracker;
+import com.android.server.net.NetworkPolicyManagerInternal;
 
 import com.google.android.collect.Lists;
 
@@ -221,18 +215,6 @@
     private boolean mLockdownEnabled;
     private LockdownVpnTracker mLockdownTracker;
 
-    /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
-    private Object mRulesLock = new Object();
-    /** Currently active network rules by UID. */
-    @GuardedBy("mRulesLock")
-    private SparseIntArray mUidRules = new SparseIntArray();
-    /** Set of ifaces that are costly. */
-    @GuardedBy("mRulesLock")
-    private ArraySet<String> mMeteredIfaces = new ArraySet<>();
-    /** Flag indicating if background data is restricted. */
-    @GuardedBy("mRulesLock")
-    private boolean mRestrictBackground;
-
     final private Context mContext;
     private int mNetworkPreference;
     // 0 is full bad, 100 is full good
@@ -246,6 +228,7 @@
     private INetworkManagementService mNetd;
     private INetworkStatsService mStatsService;
     private INetworkPolicyManager mPolicyManager;
+    private NetworkPolicyManagerInternal mPolicyManagerInternal;
 
     private String mCurrentTcpBufferSizes;
 
@@ -715,12 +698,15 @@
         mNetd = checkNotNull(netManager, "missing INetworkManagementService");
         mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
         mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
+        mPolicyManagerInternal = checkNotNull(
+                LocalServices.getService(NetworkPolicyManagerInternal.class),
+                "missing NetworkPolicyManagerInternal");
+
         mKeyStore = KeyStore.getInstance();
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
 
         try {
-            mPolicyManager.setConnectivityListener(mPolicyListener);
-            mRestrictBackground = mPolicyManager.getRestrictBackground();
+            mPolicyManager.registerListener(mPolicyListener);
         } catch (RemoteException e) {
             // ouch, no rules updates means some processes may never get network
             loge("unable to register INetworkPolicyListener" + e);
@@ -991,51 +977,22 @@
     private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
             boolean ignoreBlocked) {
         // Networks aren't blocked when ignoring blocked status
-        if (ignoreBlocked) return false;
+        if (ignoreBlocked) {
+            return false;
+        }
         // Networks are never blocked for system services
-        if (isSystem(uid)) return false;
-
-        final boolean networkMetered;
-        final int uidRules;
-
+        // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
+        if (isSystem(uid)) {
+            return false;
+        }
         synchronized (mVpns) {
             final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
             if (vpn != null && vpn.isBlockingUid(uid)) {
                 return true;
             }
         }
-
         final String iface = (lp == null ? "" : lp.getInterfaceName());
-        synchronized (mRulesLock) {
-            networkMetered = mMeteredIfaces.contains(iface);
-            uidRules = mUidRules.get(uid, RULE_NONE);
-        }
-
-        boolean allowed = true;
-        // Check Data Saver Mode first...
-        if (networkMetered) {
-            if ((uidRules & RULE_REJECT_METERED) != 0) {
-                if (LOGD_RULES) Log.d(TAG, "uid " + uid + " is blacklisted");
-                // Explicitly blacklisted.
-                allowed = false;
-            } else {
-                allowed = !mRestrictBackground
-                      || (uidRules & RULE_ALLOW_METERED) != 0
-                      || (uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0;
-                if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
-                        + " mRestrictBackground=" + mRestrictBackground
-                        + ", whitelisted=" + ((uidRules & RULE_ALLOW_METERED) != 0)
-                        + ", tempWhitelist= + ((uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0)"
-                        + ": " + allowed);
-            }
-        }
-        // ...then power restrictions.
-        if (allowed) {
-            allowed = (uidRules & RULE_REJECT_ALL) == 0;
-            if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
-                    + " rule is " + uidRulesToString(uidRules) + ": " + allowed);
-        }
-        return !allowed;
+        return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
     }
 
     private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
@@ -1481,67 +1438,24 @@
         return true;
     }
 
-    private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
         @Override
         public void onUidRulesChanged(int uid, int uidRules) {
-            // caller is NPMS, since we only register with them
-            if (LOGD_RULES) {
-                log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
-            }
-
-            synchronized (mRulesLock) {
-                // skip update when we've already applied rules
-                final int oldRules = mUidRules.get(uid, RULE_NONE);
-                if (oldRules == uidRules) return;
-
-                if (uidRules == RULE_NONE) {
-                    mUidRules.delete(uid);
-                } else {
-                    mUidRules.put(uid, uidRules);
-                }
-            }
-
             // TODO: notify UID when it has requested targeted updates
         }
-
         @Override
         public void onMeteredIfacesChanged(String[] meteredIfaces) {
-            // caller is NPMS, since we only register with them
-            if (LOGD_RULES) {
-                log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
-            }
-
-            synchronized (mRulesLock) {
-                mMeteredIfaces.clear();
-                for (String iface : meteredIfaces) {
-                    mMeteredIfaces.add(iface);
-                }
-            }
         }
-
         @Override
         public void onRestrictBackgroundChanged(boolean restrictBackground) {
-            // caller is NPMS, since we only register with them
-            if (LOGD_RULES) {
-                log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
-            }
-
-            synchronized (mRulesLock) {
-                mRestrictBackground = restrictBackground;
-            }
-
+            // TODO: relocate this specific callback in Tethering.
             if (restrictBackground) {
                 log("onRestrictBackgroundChanged(true): disabling tethering");
                 mTethering.untetherAll();
             }
         }
-
         @Override
         public void onUidPoliciesChanged(int uid, int uidPolicies) {
-            // caller is NPMS, since we only register with them
-            if (LOGD_RULES) {
-                log("onUidRulesChanged(uid=" + uid + ", uidPolicies=" + uidPolicies + ")");
-            }
         }
     };
 
@@ -1976,33 +1890,6 @@
         pw.decreaseIndent();
         pw.println();
 
-        pw.println("Metered Interfaces:");
-        pw.increaseIndent();
-        for (String value : mMeteredIfaces) {
-            pw.println(value);
-        }
-        pw.decreaseIndent();
-        pw.println();
-
-        pw.print("Restrict background: ");
-        pw.println(mRestrictBackground);
-        pw.println();
-
-        pw.println("Status for known UIDs:");
-        pw.increaseIndent();
-        final int size = mUidRules.size();
-        for (int i = 0; i < size; i++) {
-            final int uid = mUidRules.keyAt(i);
-            pw.print("UID=");
-            pw.print(uid);
-            final int uidRules = mUidRules.get(uid, RULE_NONE);
-            pw.print(" rules=");
-            pw.print(uidRulesToString(uidRules));
-            pw.println();
-        }
-        pw.println();
-        pw.decreaseIndent();
-
         pw.println("Network Requests:");
         pw.increaseIndent();
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -3437,6 +3324,10 @@
         Slog.e(TAG, s);
     }
 
+    private static void loge(String s, Throwable t) {
+        Slog.e(TAG, s, t);
+    }
+
     private static <T> T checkNotNull(T value, String message) {
         if (value == null) {
             throw new NullPointerException(message);
@@ -4197,20 +4088,16 @@
     private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
         final int uid = Binder.getCallingUid();
         if (isSystem(uid)) {
+            // Exemption for system uid.
             return;
         }
-        // if UID is restricted, don't allow them to bring up metered APNs
-        if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) == false) {
-            final int uidRules;
-            synchronized(mRulesLock) {
-                uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
-            }
-            if (mRestrictBackground && (uidRules & RULE_ALLOW_METERED) == 0
-                    && (uidRules & RULE_TEMPORARY_ALLOW_METERED) == 0) {
-                // we could silently fail or we can filter the available nets to only give
-                // them those they have access to.  Chose the more useful option.
-                networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
-            }
+        if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+            // Policy already enforced.
+            return;
+        }
+        if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
+            // If UID is restricted, don't allow them to bring up metered APNs.
+            networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
         }
     }
 
diff --git a/services/core/java/com/android/server/FontManagerService.java b/services/core/java/com/android/server/FontManagerService.java
deleted file mode 100644
index f172647..0000000
--- a/services/core/java/com/android/server/FontManagerService.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.graphics.FontListParser;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.text.FontConfig;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.font.IFontManager;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-public class FontManagerService extends IFontManager.Stub {
-    private static final String TAG = "FontManagerService";
-    private static final String FONTS_CONFIG = "/system/etc/fonts.xml";
-    private static final String SYSTEM_FONT_DIR = "/system/fonts/";
-
-    @GuardedBy("mLock")
-    private FontConfig mConfig;
-    private final Object mLock = new Object();
-
-    public static final class Lifecycle extends SystemService {
-        private final FontManagerService mService;
-
-        public Lifecycle(Context context) {
-            super(context);
-            mService = new FontManagerService();
-        }
-
-        @Override
-        public void onStart() {
-            try {
-                publishBinderService(Context.FONT_SERVICE, mService);
-            } catch (Throwable t) {
-                // Starting this service is not critical to the running of this device and should
-                // therefore not crash the device. If it fails, log the error and continue.
-                Slog.e(TAG, "Could not start the FontManagerService.", t);
-            }
-        }
-    }
-
-    @Override
-    public FontConfig getSystemFonts() {
-        synchronized (mLock) {
-            if (mConfig != null) {
-                return mConfig;
-            }
-
-            mConfig = loadFromSystem();
-            if (mConfig == null) {
-                return null;
-            }
-
-            for (FontConfig.Family family : mConfig.getFamilies()) {
-                for (FontConfig.Font font : family.getFonts()) {
-                    File fontFile = new File(SYSTEM_FONT_DIR, font.getFontName());
-                    font.setUri(Uri.fromFile(fontFile));
-                }
-            }
-
-            return mConfig;
-        }
-    }
-
-    private FontConfig loadFromSystem() {
-        File configFilename = new File(FONTS_CONFIG);
-        try {
-            FileInputStream fontsIn = new FileInputStream(configFilename);
-            return FontListParser.parse(fontsIn);
-        } catch (IOException | XmlPullParserException e) {
-            Slog.e(TAG, "Error opening " + configFilename, e);
-        }
-        return null;
-    }
-
-    public FontManagerService() {
-    }
-}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index a5debda..9218c25 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -280,6 +280,7 @@
         if (DBG) Log.d(TAG, "refreshBinding()");
         // Make sure the scorer is up-to-date
         mNetworkScorerAppManager.updateState();
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
         registerPackageMonitorIfNeeded();
         bindToScoringServiceIfNeeded();
     }
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 1a3bb35..e127eb9 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -42,7 +42,6 @@
  *
  * @hide
  */
-@VisibleForTesting
 public class NetworkScorerAppManager {
     private static final String TAG = "NetworkScorerAppManager";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -64,8 +63,7 @@
      * Returns the list of available scorer apps. The list will be empty if there are
      * no valid scorers.
      */
-    @VisibleForTesting
-    public List<NetworkScorerAppData> getAllValidScorers() {
+    List<NetworkScorerAppData> getAllValidScorers() {
         if (VERBOSE) Log.v(TAG, "getAllValidScorers()");
         final PackageManager pm = mContext.getPackageManager();
         final Intent serviceIntent = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
@@ -170,8 +168,7 @@
      *     it was disabled or uninstalled).
      */
     @Nullable
-    @VisibleForTesting
-    public NetworkScorerAppData getActiveScorer() {
+    NetworkScorerAppData getActiveScorer() {
         final int enabledSetting = getNetworkRecommendationsEnabledSetting();
         if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
             return null;
@@ -214,8 +211,7 @@
      * @return true if the scorer was changed, or false if the package is not a valid scorer or
      *         a valid network recommendation provider exists.
      */
-    @VisibleForTesting
-    public boolean setActiveScorer(String packageName) {
+    boolean setActiveScorer(String packageName) {
         final String oldPackageName = getNetworkRecommendationsPackage();
 
         if (TextUtils.equals(oldPackageName, packageName)) {
@@ -250,8 +246,7 @@
      * is no longer valid then {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} will be set
      * to <code>0</code> (disabled).
      */
-    @VisibleForTesting
-    public void updateState() {
+    void updateState() {
         final int enabledSetting = getNetworkRecommendationsEnabledSetting();
         if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
             // Don't change anything if it's forced off.
@@ -286,6 +281,56 @@
         }
     }
 
+    /**
+     * Migrates the NETWORK_SCORER_APP Setting to the USE_OPEN_WIFI_PACKAGE Setting.
+     */
+    void migrateNetworkScorerAppSettingIfNeeded() {
+        final String scorerAppPkgNameSetting =
+                mSettingsFacade.getString(mContext, Settings.Global.NETWORK_SCORER_APP);
+        if (TextUtils.isEmpty(scorerAppPkgNameSetting)) {
+            // Early exit, nothing to do.
+            return;
+        }
+
+        final NetworkScorerAppData currentAppData = getActiveScorer();
+        if (currentAppData == null) {
+            // Don't touch anything until we have an active scorer to work with.
+            return;
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, "Migrating Settings.Global.NETWORK_SCORER_APP "
+                    + "(" + scorerAppPkgNameSetting + ")...");
+        }
+
+        // If the new (useOpenWifi) Setting isn't set and the old Setting's value matches the
+        // new metadata value then update the new Setting with the old value. Otherwise it's a
+        // mismatch so we shouldn't enable the Setting automatically.
+        final ComponentName enableUseOpenWifiActivity =
+                currentAppData.getEnableUseOpenWifiActivity();
+        final String useOpenWifiSetting =
+                mSettingsFacade.getString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE);
+        if (TextUtils.isEmpty(useOpenWifiSetting)
+                && enableUseOpenWifiActivity != null
+                && scorerAppPkgNameSetting.equals(enableUseOpenWifiActivity.getPackageName())) {
+            mSettingsFacade.putString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE,
+                    scorerAppPkgNameSetting);
+            if (DEBUG) {
+                Log.d(TAG, "Settings.Global.USE_OPEN_WIFI_PACKAGE set to "
+                        + "'" + scorerAppPkgNameSetting + "'.");
+            }
+        }
+
+        // Clear out the old setting so we don't run through the migration code again.
+        mSettingsFacade.putString(mContext, Settings.Global.NETWORK_SCORER_APP, null);
+        if (DEBUG) {
+            Log.d(TAG, "Settings.Global.NETWORK_SCORER_APP migration complete.");
+            final String setting =
+                    mSettingsFacade.getString(mContext, Settings.Global.USE_OPEN_WIFI_PACKAGE);
+            Log.d(TAG, "Settings.Global.USE_OPEN_WIFI_PACKAGE is: '" + setting + "'.");
+        }
+    }
+
     private String getDefaultPackageSetting() {
         return mContext.getResources().getString(
                 R.string.config_defaultNetworkRecommendationProviderPackage);
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 421d5a6..c105b12 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.app.ActivityThread;
 import android.content.Context;
 import android.os.IBinder;
 import android.os.ServiceManager;
@@ -104,6 +105,16 @@
     }
 
     /**
+     * Get the system UI context. This context is to be used for displaying UI. It is themable,
+     * which means resources can be overridden at runtime. Do not use to retrieve properties that
+     * configure the behavior of the device that is not UX related.
+     */
+    public final Context getUiContext() {
+        // This has already been set up by the time any SystemServices are created.
+        return ActivityThread.currentActivityThread().getSystemUiContext();
+    }
+
+    /**
      * Returns true if the system is running in safe mode.
      * TODO: we should define in which phase this becomes valid
      */
diff --git a/services/core/java/com/android/server/ThreadPriorityBooster.java b/services/core/java/com/android/server/ThreadPriorityBooster.java
new file mode 100644
index 0000000..17965d0
--- /dev/null
+++ b/services/core/java/com/android/server/ThreadPriorityBooster.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import android.os.Process;
+
+/**
+ * Utility class to boost threads in sections where important locks are held.
+ */
+public class ThreadPriorityBooster {
+
+    private final int mBoostToPriority;
+    private final int mLockGuardIndex;
+
+    private final ThreadLocal<PriorityState> mThreadState = new ThreadLocal<PriorityState>() {
+        @Override protected PriorityState initialValue() {
+            return new PriorityState();
+        }
+    };
+
+    public ThreadPriorityBooster(int boostToPriority, int lockGuardIndex) {
+        mBoostToPriority = boostToPriority;
+        mLockGuardIndex = lockGuardIndex;
+    }
+
+    public void boost() {
+        final int tid = Process.myTid();
+        final int prevPriority = Process.getThreadPriority(tid);
+        PriorityState state = mThreadState.get();
+        if (state.regionCounter == 0 && prevPriority > mBoostToPriority) {
+            state.prevPriority = prevPriority;
+            Process.setThreadPriority(tid, mBoostToPriority);
+        }
+        state.regionCounter++;
+        if (LockGuard.ENABLED) {
+            LockGuard.guard(mLockGuardIndex);
+        }
+    }
+
+    public void reset() {
+        PriorityState state = mThreadState.get();
+        state.regionCounter--;
+        if (state.regionCounter == 0 && state.prevPriority > mBoostToPriority) {
+            Process.setThreadPriority(Process.myTid(), state.prevPriority);
+        }
+    }
+
+    private static class PriorityState {
+
+        /**
+         * Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
+         * the current thread is currently in. When it drops down to zero, we will no longer boost
+         * the thread's priority.
+         */
+        int regionCounter;
+
+        /**
+         * The thread's previous priority before boosting.
+         */
+        int prevPriority;
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d996ee2..738365d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -123,7 +123,6 @@
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -191,17 +190,14 @@
     }
 
     private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
-    private final AtomicInteger mNotificationIds =
-            new AtomicInteger(SystemMessage.ACCOUNT_MANAGER_BASE);
 
     static class UserAccounts {
         private final int userId;
         final AccountsDb accountsDb;
-        private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
-                credentialsPermissionNotificationIds =
-                new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
-        private final HashMap<Account, Integer> signinRequiredNotificationIds =
-                new HashMap<Account, Integer>();
+        private final HashMap<Pair<Pair<Account, String>, Integer>, NotificationId>
+                credentialsPermissionNotificationIds = new HashMap<>();
+        private final HashMap<Account, NotificationId> signinRequiredNotificationIds
+                = new HashMap<>();
         final Object cacheLock = new Object();
         final Object dbLock = new Object(); // if needed, dbLock must be obtained before cacheLock
         /** protected by the {@link #cacheLock} */
@@ -431,14 +427,13 @@
     public boolean addAccountExplicitlyWithVisibility(Account account, String password,
             Bundle extras, Map packageToVisibility) {
         Bundle.setDefusable(extras, true);
-
-        final int callingUid = Binder.getCallingUid();
+        int callingUid = Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
         Preconditions.checkNotNull(account, "account cannot be null");
-        int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
                     callingUid, account.type);
@@ -465,9 +460,9 @@
     public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
             String accountType) {
         int callingUid = Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
         boolean isSystemUid = UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
-        List<String> managedTypes =
-                getTypesForCaller(callingUid, UserHandle.getUserId(callingUid), isSystemUid);
+        List<String> managedTypes = getTypesForCaller(callingUid, userId, isSystemUid);
 
         if ((accountType != null && !managedTypes.contains(accountType))
                 || (accountType == null && !isSystemUid)) {
@@ -482,8 +477,9 @@
 
         long identityToken = clearCallingIdentity();
         try {
+            UserAccounts accounts = getUserAccounts(userId);
             return getAccountsAndVisibilityForPackage(packageName, managedTypes, callingUid,
-                    getUserAccounts(UserHandle.getUserId(callingUid)));
+                    accounts);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -494,12 +490,8 @@
      */
     private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
             List<String> accountTypes, Integer callingUid, UserAccounts accounts) {
-        int uid = 0;
-        try {
-            uid = mPackageManager.getPackageUidAsUser(packageName,
-                    UserHandle.getUserId(callingUid));
-        } catch (NameNotFoundException e) {
-            Log.d(TAG, "Package not found " + e.getMessage());
+        if (!packageExistsForUser(packageName, accounts.userId)) {
+            Log.d(TAG, "Package not found " + packageName);
             return new LinkedHashMap<>();
         }
 
@@ -524,19 +516,26 @@
     public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
         Preconditions.checkNotNull(account, "account cannot be null");
         int callingUid = Binder.getCallingUid();
-        int userId = UserHandle.getUserId(callingUid);
-        UserAccounts accounts = getUserAccounts(userId);
+        int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)
                 && !isSystemUid(callingUid)) {
             String msg =
                     String.format("uid %s cannot get secrets for account %s", callingUid, account);
             throw new SecurityException(msg);
         }
-        synchronized (accounts.dbLock) {
-            synchronized (accounts.cacheLock) {
-                return getPackagesAndVisibilityForAccountLocked(account, accounts);
+
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts accounts = getUserAccounts(userId);
+            synchronized (accounts.dbLock) {
+                synchronized (accounts.cacheLock) {
+                    return getPackagesAndVisibilityForAccountLocked(account, accounts);
+                }
             }
+        } finally {
+            restoreCallingIdentity(identityToken);
         }
+
     }
 
     /**
@@ -564,8 +563,8 @@
         Preconditions.checkNotNull(account, "account cannot be null");
         Preconditions.checkNotNull(packageName, "packageName cannot be null");
         int callingUid = Binder.getCallingUid();
-        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
-        if (!isAccountManagedByCaller(account.type, callingUid, accounts.userId)
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)
             && !isSystemUid(callingUid)) {
             String msg = String.format(
                     "uid %s cannot get secrets for accounts of type: %s",
@@ -573,7 +572,13 @@
                     account.type);
             throw new SecurityException(msg);
         }
-        return resolveAccountVisibility(account, packageName, accounts);
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts accounts = getUserAccounts(userId);
+            return resolveAccountVisibility(account, packageName, accounts);
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
     }
 
     /**
@@ -712,8 +717,8 @@
         Preconditions.checkNotNull(account, "account cannot be null");
         Preconditions.checkNotNull(packageName, "packageName cannot be null");
         int callingUid = Binder.getCallingUid();
-        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
-        if (!isAccountManagedByCaller(account.type, callingUid, accounts.userId)
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)
             && !isSystemUid(callingUid)) {
             String msg = String.format(
                     "uid %s cannot get secrets for accounts of type: %s",
@@ -721,8 +726,14 @@
                     account.type);
             throw new SecurityException(msg);
         }
-        return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts accounts = getUserAccounts(userId);
+            return setAccountVisibility(account, packageName, newVisibility, true /* notify */,
                 accounts);
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
     }
 
     /**
@@ -809,8 +820,15 @@
     public void registerAccountListener(String[] accountTypes, String opPackageName) {
         int callingUid = Binder.getCallingUid();
         mAppOpsManager.checkPackage(callingUid, opPackageName);
-        registerAccountListener(accountTypes, opPackageName,
-            getUserAccounts(UserHandle.getUserId(callingUid)));
+
+        int userId = UserHandle.getCallingUserId();
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts accounts = getUserAccounts(userId);
+            registerAccountListener(accountTypes, opPackageName, accounts);
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
     }
 
     private void registerAccountListener(String[] accountTypes, String opPackageName,
@@ -836,7 +854,18 @@
     public void unregisterAccountListener(String[] accountTypes, String opPackageName) {
         int callingUid = Binder.getCallingUid();
         mAppOpsManager.checkPackage(callingUid, opPackageName);
-        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
+        int userId = UserHandle.getCallingUserId();
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts accounts = getUserAccounts(userId);
+            unregisterAccountListener(accountTypes, opPackageName, accounts);
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
+    private void unregisterAccountListener(String[] accountTypes, String opPackageName,
+            UserAccounts accounts) {
         synchronized (accounts.mReceiversForType) {
             if (accountTypes == null) {
                 // null for any type
@@ -907,7 +936,7 @@
             long identityToken = clearCallingIdentity();
             try {
                 mPackageManager.getPackageUidAsUser(packageName, userId);
-                return true; // package exist
+                return true;
             } finally {
                 restoreCallingIdentity(identityToken);
             }
@@ -1863,12 +1892,12 @@
          */
         cancelNotification(
                 getSigninRequiredNotificationId(accounts, accountToRename),
-                 new UserHandle(accounts.userId));
+                new UserHandle(accounts.userId));
         synchronized(accounts.credentialsPermissionNotificationIds) {
             for (Pair<Pair<Account, String>, Integer> pair:
                     accounts.credentialsPermissionNotificationIds.keySet()) {
                 if (accountToRename.equals(pair.first.first)) {
-                    int id = accounts.credentialsPermissionNotificationIds.get(pair);
+                    NotificationId id = accounts.credentialsPermissionNotificationIds.get(pair);
                     cancelNotification(id, new UserHandle(accounts.userId));
                 }
             }
@@ -2021,7 +2050,7 @@
             for (Pair<Pair<Account, String>, Integer> pair:
                 accounts.credentialsPermissionNotificationIds.keySet()) {
                 if (account.equals(pair.first.first)) {
-                    int id = accounts.credentialsPermissionNotificationIds.get(pair);
+                    NotificationId id = accounts.credentialsPermissionNotificationIds.get(pair);
                     cancelNotification(id, user);
                 }
             }
@@ -2912,8 +2941,8 @@
             // the intent from a non-Activity context. This is the default behavior.
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         }
-        intent.addCategory(String.valueOf(getCredentialPermissionNotificationId(account,
-                authTokenType, uid) + (packageName != null ? packageName : "")));
+        intent.addCategory(getCredentialPermissionNotificationId(account,
+                authTokenType, uid).mTag + (packageName != null ? packageName : ""));
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
         intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
@@ -2922,33 +2951,39 @@
         return intent;
     }
 
-    private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
-            int uid) {
-        Integer id;
+    private NotificationId getCredentialPermissionNotificationId(Account account,
+            String authTokenType, int uid) {
+        NotificationId nId;
         UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
         synchronized (accounts.credentialsPermissionNotificationIds) {
             final Pair<Pair<Account, String>, Integer> key =
                     new Pair<Pair<Account, String>, Integer>(
                             new Pair<Account, String>(account, authTokenType), uid);
-            id = accounts.credentialsPermissionNotificationIds.get(key);
-            if (id == null) {
-                id = mNotificationIds.incrementAndGet();
-                accounts.credentialsPermissionNotificationIds.put(key, id);
+            nId = accounts.credentialsPermissionNotificationIds.get(key);
+            if (nId == null) {
+                String tag = TAG + ":" + SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION
+                        + ":" + account.hashCode() + ":" + authTokenType.hashCode();
+                int id = SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION;
+                nId = new NotificationId(tag, id);
+                accounts.credentialsPermissionNotificationIds.put(key, nId);
             }
         }
-        return id;
+        return nId;
     }
 
-    private Integer getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
-        Integer id;
+    private NotificationId getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
+        NotificationId nId;
         synchronized (accounts.signinRequiredNotificationIds) {
-            id = accounts.signinRequiredNotificationIds.get(account);
-            if (id == null) {
-                id = mNotificationIds.incrementAndGet();
-                accounts.signinRequiredNotificationIds.put(account, id);
+            nId = accounts.signinRequiredNotificationIds.get(account);
+            if (nId == null) {
+                String tag = TAG + ":" + SystemMessage.NOTE_ACCOUNT_REQUIRE_SIGNIN
+                        + ":" + account.hashCode();
+                int id = SystemMessage.NOTE_ACCOUNT_REQUIRE_SIGNIN;
+                nId = new NotificationId(tag, id);
+                accounts.signinRequiredNotificationIds.put(account, nId);
             }
         }
-        return id;
+        return nId;
     }
 
     @Override
@@ -4931,8 +4966,8 @@
                 createNoCredentialsPermissionNotification(account, intent, packageName, userId);
             } else {
                 Context contextForUser = getContextForUser(new UserHandle(userId));
-                final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
-                intent.addCategory(String.valueOf(notificationId));
+                final NotificationId id = getSigninRequiredNotificationId(accounts, account);
+                intent.addCategory(id.mTag);
 
                 final String notificationTitleFormat =
                         contextForUser.getText(R.string.notification_title).toString();
@@ -4948,21 +4983,21 @@
                                 mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
                                 null, new UserHandle(userId)))
                         .build();
-                installNotification(notificationId, n, packageName, userId);
+                installNotification(id, n, packageName, userId);
             }
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    private void installNotification(int notificationId, final Notification notification,
+    private void installNotification(NotificationId id, final Notification notification,
             String packageName, int userId) {
         final long token = clearCallingIdentity();
         try {
             INotificationManager notificationManager = mInjector.getNotificationManager();
             try {
-                notificationManager.enqueueNotificationWithTag(packageName, packageName, null,
-                        notificationId, notification, new int[1], userId);
+                notificationManager.enqueueNotificationWithTag(packageName, packageName,
+                        id.mTag, id.mId, notification, new int[1], userId);
             } catch (RemoteException e) {
                 /* ignore - local call */
             }
@@ -4971,15 +5006,15 @@
         }
     }
 
-    private void cancelNotification(int id, UserHandle user) {
+    private void cancelNotification(NotificationId id, UserHandle user) {
         cancelNotification(id, mContext.getPackageName(), user);
     }
 
-    private void cancelNotification(int id, String packageName, UserHandle user) {
+    private void cancelNotification(NotificationId id, String packageName, UserHandle user) {
         long identityToken = clearCallingIdentity();
         try {
             INotificationManager service = mInjector.getNotificationManager();
-            service.cancelNotificationWithTag(packageName, null, id, user.getIdentifier());
+            service.cancelNotificationWithTag(packageName, id.mTag, id.mId, user.getIdentifier());
         } catch (RemoteException e) {
             /* ignore - local call */
         } finally {
@@ -5893,4 +5928,14 @@
             return NotificationManager.getService();
         }
     }
+
+    private class NotificationId {
+        final String mTag;
+        private final int mId;
+
+        NotificationId(String tag, int type) {
+            mTag = tag;
+            mId = type;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b4ea49b..19fc2b8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,12 +17,12 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.CHANGE_CONFIGURATION;
+import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -42,13 +42,49 @@
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
+import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
 import static android.os.Build.VERSION_CODES.N;
+import static android.os.Process.BLUETOOTH_UID;
+import static android.os.Process.FIRST_APPLICATION_UID;
+import static android.os.Process.FIRST_ISOLATED_UID;
+import static android.os.Process.LAST_ISOLATED_UID;
+import static android.os.Process.NFC_UID;
+import static android.os.Process.PHONE_UID;
 import static android.os.Process.PROC_CHAR;
 import static android.os.Process.PROC_OUT_LONG;
 import static android.os.Process.PROC_PARENS;
 import static android.os.Process.PROC_SPACE_TERM;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
-import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
+import static android.os.Process.ProcessStartResult;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SCHED_FIFO;
+import static android.os.Process.SCHED_OTHER;
+import static android.os.Process.SCHED_RESET_ON_FORK;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SIGNAL_QUIT;
+import static android.os.Process.SIGNAL_USR1;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_GROUP_BG_NONINTERACTIVE;
+import static android.os.Process.THREAD_GROUP_DEFAULT;
+import static android.os.Process.THREAD_GROUP_TOP_APP;
+import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
+import static android.os.Process.getFreeMemory;
+import static android.os.Process.getThreadPriority;
+import static android.os.Process.getTotalMemory;
+import static android.os.Process.isThreadInProcess;
+import static android.os.Process.killProcess;
+import static android.os.Process.killProcessQuiet;
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
+import static android.os.Process.readProcFile;
+import static android.os.Process.removeAllProcessGroups;
+import static android.os.Process.sendSignal;
+import static android.os.Process.setProcessGroup;
+import static android.os.Process.setThreadPriority;
+import static android.os.Process.setThreadScheduler;
+import static android.os.Process.startWebView;
+import static android.os.Process.zygoteProcess;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEBUG_APP;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -323,7 +359,6 @@
 import android.view.View;
 import android.view.WindowManager;
 
-import com.android.internal.notification.SystemNotificationChannels;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -341,6 +376,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.IResultReceiver;
@@ -367,6 +403,7 @@
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
+import com.android.server.ThreadPriorityBooster;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.firewall.IntentFirewall;
@@ -409,7 +446,6 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import dalvik.system.VMRuntime;
-
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
 
@@ -547,7 +583,7 @@
     // Maximum number of persisted Uri grants a package is allowed
     static final int MAX_PERSISTED_URI_GRANTS = 128;
 
-    static final int MY_PID = Process.myPid();
+    static final int MY_PID = myPid();
 
     static final String[] EMPTY_STRING_ARRAY = new String[0];
 
@@ -680,13 +716,13 @@
                     if (mTopAppVrThreadTid > 0) {
                         // Ensure that when entering persistent VR mode the last top-app loses
                         // SCHED_FIFO.
-                        Process.setThreadScheduler(mTopAppVrThreadTid, Process.SCHED_OTHER, 0);
+                        setThreadScheduler(mTopAppVrThreadTid, SCHED_OTHER, 0);
                         mTopAppVrThreadTid = 0;
                     }
                 } else if (mPersistentVrThreadTid > 0) {
                     // Ensure that when leaving persistent VR mode we reschedule the high priority
                     // persistent thread.
-                    Process.setThreadScheduler(mPersistentVrThreadTid, Process.SCHED_OTHER, 0);
+                    setThreadScheduler(mPersistentVrThreadTid, SCHED_OTHER, 0);
                     mPersistentVrThreadTid = 0;
                 }
             }
@@ -773,42 +809,15 @@
                 && !mKeyguardController.isKeyguardShowing();
     }
 
-    private static final class PriorityState {
-        // Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
-        // the current thread is currently in. When it drops down to zero, we will no longer boost
-        // the thread's priority.
-        private int regionCounter = 0;
-
-        // The thread's previous priority before boosting.
-        private int prevPriority = Integer.MIN_VALUE;
-    }
-
-    static ThreadLocal<PriorityState> sThreadPriorityState = new ThreadLocal<PriorityState>() {
-        @Override protected PriorityState initialValue() {
-            return new PriorityState();
-        }
-    };
+    private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+            THREAD_PRIORITY_FOREGROUND, LockGuard.INDEX_ACTIVITY);
 
     static void boostPriorityForLockedSection() {
-        int tid = Process.myTid();
-        int prevPriority = Process.getThreadPriority(tid);
-        PriorityState state = sThreadPriorityState.get();
-        if (state.regionCounter == 0 && prevPriority > -2) {
-            state.prevPriority = prevPriority;
-            Process.setThreadPriority(tid, -2);
-        }
-        state.regionCounter++;
-        if (LockGuard.ENABLED) {
-            LockGuard.guard(LockGuard.INDEX_ACTIVITY);
-        }
+        sThreadPriorityBooster.boost();
     }
 
     static void resetPriorityAfterLockedSection() {
-        PriorityState state = sThreadPriorityState.get();
-        state.regionCounter--;
-        if (state.regionCounter == 0 && state.prevPriority > -2) {
-            Process.setThreadPriority(Process.myTid(), state.prevPriority);
-        }
+        sThreadPriorityBooster.reset();
     }
 
     public class PendingAssistExtras extends Binder implements Runnable {
@@ -889,7 +898,7 @@
      * Non-persistent app uid whitelist for background restrictions
      */
     int[] mBackgroundUidWhitelist = new int[] {
-            Process.BLUETOOTH_UID
+            BLUETOOTH_UID
     };
 
     /**
@@ -1350,7 +1359,13 @@
     @GuardedBy("this") boolean mLaunchWarningShown = false;
     @GuardedBy("this") boolean mCheckedForSetup = false;
 
-    Context mContext;
+    final Context mContext;
+
+    /**
+     * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can
+     * change at runtime. Use mContext for non-UI purposes.
+     */
+    final Context mUiContext;
 
     /**
      * The time at which we will allow normal application switches again,
@@ -1852,7 +1867,7 @@
             } break;
             case SHOW_FACTORY_ERROR_UI_MSG: {
                 Dialog d = new FactoryErrorDialog(
-                    mContext, msg.getData().getCharSequence("msg"));
+                        mUiContext, msg.getData().getCharSequence("msg"));
                 d.show();
                 ensureBootCompleted();
             } break;
@@ -1863,7 +1878,7 @@
                         if (!app.waitedForDebugger) {
                             Dialog d = new AppWaitingForDebuggerDialog(
                                     ActivityManagerService.this,
-                                    mContext, app);
+                                    mUiContext, app);
                             app.waitDialog = d;
                             app.waitedForDebugger = true;
                             d.show();
@@ -1878,24 +1893,24 @@
             } break;
             case SHOW_UID_ERROR_UI_MSG: {
                 if (mShowDialogs) {
-                    AlertDialog d = new BaseErrorDialog(mContext);
+                    AlertDialog d = new BaseErrorDialog(mUiContext);
                     d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
                     d.setCancelable(false);
-                    d.setTitle(mContext.getText(R.string.android_system_label));
-                    d.setMessage(mContext.getText(R.string.system_error_wipe_data));
-                    d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+                    d.setTitle(mUiContext.getText(R.string.android_system_label));
+                    d.setMessage(mUiContext.getText(R.string.system_error_wipe_data));
+                    d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
                             obtainMessage(DISMISS_DIALOG_UI_MSG, d));
                     d.show();
                 }
             } break;
             case SHOW_FINGERPRINT_ERROR_UI_MSG: {
                 if (mShowDialogs) {
-                    AlertDialog d = new BaseErrorDialog(mContext);
+                    AlertDialog d = new BaseErrorDialog(mUiContext);
                     d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
                     d.setCancelable(false);
-                    d.setTitle(mContext.getText(R.string.android_system_label));
-                    d.setMessage(mContext.getText(R.string.system_error_manufacturer));
-                    d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+                    d.setTitle(mUiContext.getText(R.string.android_system_label));
+                    d.setMessage(mUiContext.getText(R.string.system_error_manufacturer));
+                    d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.ok),
                             obtainMessage(DISMISS_DIALOG_UI_MSG, d));
                     d.show();
                 }
@@ -1919,7 +1934,7 @@
                             if (mode == ActivityManager.COMPAT_MODE_DISABLED
                                     || mode == ActivityManager.COMPAT_MODE_ENABLED) {
                                 mCompatModeDialog = new CompatModeDialog(
-                                        ActivityManagerService.this, mContext,
+                                        ActivityManagerService.this, mUiContext,
                                         ar.info.applicationInfo);
                                 mCompatModeDialog.show();
                             }
@@ -1939,7 +1954,7 @@
                             ar.packageName)) {
                         // TODO(multi-display): Show dialog on appropriate display.
                         mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
-                                ActivityManagerService.this, mContext, ar.info.applicationInfo);
+                                ActivityManagerService.this, mUiContext, ar.info.applicationInfo);
                         mUnsupportedDisplaySizeDialog.show();
                     }
                 }
@@ -2461,12 +2476,12 @@
                                 if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
                                     try {
                                         if (mVrState == VR_MODE) {
-                                            Process.setThreadScheduler(proc.vrThreadTid,
-                                                Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                            setThreadScheduler(proc.vrThreadTid,
+                                                SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
                                             mTopAppVrThreadTid = proc.vrThreadTid;
                                         } else {
-                                            Process.setThreadScheduler(proc.vrThreadTid,
-                                                Process.SCHED_OTHER, 0);
+                                            setThreadScheduler(proc.vrThreadTid,
+                                                SCHED_OTHER, 0);
                                             mTopAppVrThreadTid = 0;
                                         }
                                     } catch (IllegalArgumentException e) {
@@ -2523,7 +2538,7 @@
                     final List<ProcessCpuTracker.Stats> stats;
                     synchronized (mProcessCpuTracker) {
                         stats = mProcessCpuTracker.getStats( (st)-> {
-                            return st.vsize > 0 && st.uid < Process.FIRST_APPLICATION_UID;
+                            return st.vsize > 0 && st.uid < FIRST_APPLICATION_UID;
                         });
                     }
                     final int N = stats.size();
@@ -2731,6 +2746,7 @@
     public ActivityManagerService(Injector injector) {
         mInjector = injector;
         mContext = mInjector.getContext();
+        mUiContext = null;
         GL_ES_VERSION = 0;
         mActivityStarter = null;
         mAppErrors = null;
@@ -2762,8 +2778,10 @@
         LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
         mInjector = new Injector();
         mContext = systemContext;
+
         mFactoryTest = FactoryTest.getMode();
         mSystemThread = ActivityThread.currentActivityThread();
+        mUiContext = mSystemThread.getSystemUiContext();
 
         Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
 
@@ -2771,7 +2789,7 @@
                 com.android.internal.R.bool.config_permissionReviewRequired);
 
         mHandlerThread = new ServiceThread(TAG,
-                android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+                THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
         mHandlerThread.start();
         mHandler = new MainHandler(mHandlerThread.getLooper());
         mUiHandler = mInjector.getUiHandler(this);
@@ -2792,7 +2810,7 @@
         /* static; one-time init here */
         if (sKillHandler == null) {
             sKillThread = new ServiceThread(TAG + ":kill",
-                    android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
+                    THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
             sKillThread.start();
             sKillHandler = new KillHandler(sKillThread.getLooper());
         }
@@ -2806,7 +2824,7 @@
 
         mServices = new ActiveServices(this);
         mProviderMap = new ProviderMap(this);
-        mAppErrors = new AppErrors(mContext, this);
+        mAppErrors = new AppErrors(mUiContext, this);
 
         // TODO: Move creation of battery stats service outside of activity manager service.
         File dataDir = Environment.getDataDirectory();
@@ -2849,7 +2867,7 @@
         mTempConfig.setToDefaults();
         mTempConfig.setLocales(LocaleList.getDefault());
         mConfigurationSeq = mTempConfig.seq = 1;
-        mStackSupervisor = new ActivityStackSupervisor(this);
+        mStackSupervisor = createStackSupervisor();
         mStackSupervisor.onConfigurationChanged(mTempConfig);
         mKeyguardController = mStackSupervisor.mKeyguardController;
         mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
@@ -2897,6 +2915,10 @@
         Watchdog.getInstance().addThread(mHandler);
     }
 
+    protected ActivityStackSupervisor createStackSupervisor() {
+        return new ActivityStackSupervisor(this, mHandler.getLooper());
+    }
+
     public void setSystemServiceManager(SystemServiceManager mgr) {
         mSystemServiceManager = mgr;
     }
@@ -2906,7 +2928,7 @@
     }
 
     private void start() {
-        Process.removeAllProcessGroups();
+        removeAllProcessGroups();
         mProcessCpuThread.start();
 
         mBatteryStatsService.publish(mContext);
@@ -3114,7 +3136,7 @@
         synchronized (this) {
             broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
                     AppOpsManager.OP_NONE, null, false, false,
-                    -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
+                    -1, SYSTEM_UID, UserHandle.USER_ALL);
         }
     }
 
@@ -3151,7 +3173,8 @@
      * {@link ActivityStack#setResumedActivityLocked} when an activity is resumed.
      */
     void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
-        if (r.task.isApplicationTask()) {
+        final TaskRecord task = r.getTask();
+        if (task.isApplicationTask()) {
             if (mCurAppTimeTracker != r.appTimeTracker) {
                 // We are switching app tracking.  Complete the current one.
                 if (mCurAppTimeTracker != null) {
@@ -3174,17 +3197,18 @@
         // TODO: VI Maybe r.task.voiceInteractor || r.voiceInteractor != null
         // TODO: Probably not, because we don't want to resume voice on switching
         // back to this activity
-        if (r.task.voiceInteractor != null) {
-            startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
+        if (task.voiceInteractor != null) {
+            startRunningVoiceLocked(task.voiceSession, r.info.applicationInfo.uid);
         } else {
             finishRunningVoiceLocked();
 
             if (mLastResumedActivity != null) {
                 final IVoiceInteractionSession session;
 
-                if (mLastResumedActivity.task != null
-                        && mLastResumedActivity.task.voiceSession != null) {
-                    session = mLastResumedActivity.task.voiceSession;
+                final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
+                if (lastResumedActivityTask != null
+                        && lastResumedActivityTask.voiceSession != null) {
+                    session = lastResumedActivityTask.voiceSession;
                 } else {
                     session = mLastResumedActivity.voiceSession;
                 }
@@ -3317,7 +3341,7 @@
     final void showAskCompatModeDialogLocked(ActivityRecord r) {
         Message msg = Message.obtain();
         msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
-        msg.obj = r.task.askedCompatMode ? null : r;
+        msg.obj = r.getTask().askedCompatMode ? null : r;
         mUiHandler.sendMessage(msg);
     }
 
@@ -3384,7 +3408,7 @@
         if (lrui >= 0) {
             if (!app.killed) {
                 Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app);
-                Process.killProcessQuiet(app.pid);
+                killProcessQuiet(app.pid);
                 killProcessGroup(app.uid, app.pid);
             }
             if (lrui <= mLruProcessActivityStart) {
@@ -3593,7 +3617,7 @@
     }
 
     final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
-        if (uid == Process.SYSTEM_UID) {
+        if (uid == SYSTEM_UID) {
             // The system gets to run in any process.  If there are multiple
             // processes with the same uid, just pick the first (this
             // should never happen).
@@ -3659,7 +3683,7 @@
             // closest thing to a parent's uid is SYSTEM_UID.
             // The only important thing here is to keep AI.uid != PR.uid, in order to trigger
             // the |isolated| logic in the ProcessRecord constructor.
-            info.uid = Process.SYSTEM_UID;
+            info.uid = SYSTEM_UID;
             info.processName = processName;
             info.className = entryPoint;
             info.packageName = "android";
@@ -3954,9 +3978,9 @@
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                     app.processName);
             checkTime(startTime, "startProcess: asking zygote to start proc");
-            Process.ProcessStartResult startResult;
+            ProcessStartResult startResult;
             if (hostingType.equals("webview_service")) {
-                startResult = Process.startWebView(entryPoint,
+                startResult = startWebView(entryPoint,
                         app.processName, uid, uid, gids, debugFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, entryPointArgs);
@@ -4193,7 +4217,7 @@
     }
 
     void enforceShellRestriction(String restriction, int userHandle) {
-        if (Binder.getCallingUid() == Process.SHELL_UID) {
+        if (Binder.getCallingUid() == SHELL_UID) {
             if (userHandle < 0 || mUserController.hasUserRestriction(restriction, userHandle)) {
                 throw new SecurityException("Shell does not have permission to access user "
                         + userHandle);
@@ -4559,7 +4583,7 @@
             if (sourceRecord.app == null) {
                 throw new SecurityException("Called without a process attached to activity");
             }
-            if (UserHandle.getAppId(sourceRecord.app.uid) != Process.SYSTEM_UID) {
+            if (UserHandle.getAppId(sourceRecord.app.uid) != SYSTEM_UID) {
                 // This is still okay, as long as this activity is running under the
                 // uid of the original calling activity.
                 if (sourceRecord.app.uid != sourceRecord.launchedFromUid) {
@@ -4723,7 +4747,7 @@
             if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
                 throw new SecurityException("Only focused activity can call startVoiceInteraction");
             }
-            if (mRunningVoice != null || activity.task.voiceSession != null
+            if (mRunningVoice != null || activity.getTask().voiceSession != null
                     || activity.voiceSession != null) {
                 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
                 return;
@@ -5033,7 +5057,7 @@
                 return true;
             }
             // Keep track of the root activity of the task before we finish it
-            TaskRecord tr = r.task;
+            TaskRecord tr = r.getTask();
             ActivityRecord rootR = tr.getRootActivity();
             if (rootR == null) {
                 Slog.w(TAG, "Finishing task with all activities already finished");
@@ -5170,7 +5194,7 @@
 
                 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
                 // can finish.
-                final TaskRecord task = r.task;
+                final TaskRecord task = r.getTask();
                 if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV &&
                         mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
                     mStackSupervisor.showLockTaskToast();
@@ -5411,7 +5435,7 @@
 
         if (!app.killed) {
             if (!fromBinderDied) {
-                Process.killProcessQuiet(pid);
+                killProcessQuiet(pid);
             }
             killProcessGroup(app.uid, pid);
             app.killed = true;
@@ -5506,7 +5530,7 @@
         }
 
         public void dumpWithTimeout(int pid) {
-            Process.sendSignal(pid, Process.SIGNAL_QUIT);
+            sendSignal(pid, SIGNAL_QUIT);
             synchronized (this) {
                 try {
                     wait(TRACE_DUMP_TIMEOUT_MS); // Wait for traces file to be closed.
@@ -5761,7 +5785,7 @@
                     intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                     intent.putExtra(Intent.EXTRA_UID, pkgUidF);
                     intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
-                    broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+                    broadcastIntentInPackage("android", SYSTEM_UID, intent,
                             null, null, 0, null, null, null, null, false, false, userIdF);
 
                     if (observer != null) {
@@ -5979,7 +6003,7 @@
     public void addPackageDependency(String packageName) {
         synchronized (this) {
             int callingPid = Binder.getCallingPid();
-            if (callingPid == Process.myPid()) {
+            if (callingPid == myPid()) {
                 //  Yeah, um, no.
                 return;
             }
@@ -6011,7 +6035,7 @@
         }
         int callerUid = Binder.getCallingUid();
         // Only the system server can kill an application
-        if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
+        if (UserHandle.getAppId(callerUid) == SYSTEM_UID) {
             // Post an aysnc message to kill the application
             Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
             msg.arg1 = appId;
@@ -6038,7 +6062,7 @@
             synchronized (this) {
                 // Only allow this from foreground processes, so that background
                 // applications can't abuse it to prevent system UI from being shown.
-                if (uid >= Process.FIRST_APPLICATION_UID) {
+                if (uid >= FIRST_APPLICATION_UID) {
                     ProcessRecord proc;
                     synchronized (mPidsSelfLocked) {
                         proc = mPidsSelfLocked.get(pid);
@@ -6069,7 +6093,7 @@
 
         broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
                 AppOpsManager.OP_NONE, null, false, false,
-                -1, Process.SYSTEM_UID, UserHandle.USER_ALL);
+                -1, SYSTEM_UID, UserHandle.USER_ALL);
     }
 
     @Override
@@ -6135,7 +6159,7 @@
 
         int callerUid = Binder.getCallingUid();
         // Only the system server can kill an application
-        if (callerUid == Process.SYSTEM_UID) {
+        if (callerUid == SYSTEM_UID) {
             synchronized (this) {
                 ProcessRecord app = getProcessRecordLocked(processName, uid, true);
                 if (app != null && app.thread != null) {
@@ -6171,7 +6195,7 @@
         intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
         broadcastIntentLocked(null, null, intent,
                 null, null, 0, null, null, null, AppOpsManager.OP_NONE,
-                null, false, false, MY_PID, Process.SYSTEM_UID, UserHandle.getUserId(uid));
+                null, false, false, MY_PID, SYSTEM_UID, UserHandle.getUserId(uid));
     }
 
 
@@ -6688,7 +6712,7 @@
                     + " (IApplicationThread " + thread + "); dropping process");
             EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
             if (pid > 0 && pid != MY_PID) {
-                Process.killProcessQuiet(pid);
+                killProcessQuiet(pid);
                 //TODO: killProcessGroup(app.info.uid, pid);
             } else {
                 try {
@@ -6796,7 +6820,7 @@
             // If the app is being launched for restore or full backup, set it up specially
             boolean isRestrictedBackupMode = false;
             if (mBackupTarget != null && mBackupAppName.equals(processName)) {
-                isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
+                isRestrictedBackupMode = mBackupTarget.appInfo.uid >= FIRST_APPLICATION_UID
                         && ((mBackupTarget.backupMode == BackupRecord.RESTORE)
                                 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
                                 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
@@ -7019,7 +7043,7 @@
 
     @Override
     public void showBootMessage(final CharSequence msg, final boolean always) {
-        if (Binder.getCallingUid() != Process.myUid()) {
+        if (Binder.getCallingUid() != myUid()) {
             throw new SecurityException();
         }
         mWindowManager.showBootMessage(msg, always);
@@ -7056,7 +7080,7 @@
 
         ArraySet<String> completedIsas = new ArraySet<String>();
         for (String abi : Build.SUPPORTED_ABIS) {
-            Process.zygoteProcess.establishZygoteConnectionForAbi(abi);
+            zygoteProcess.establishZygoteConnectionForAbi(abi);
             final String instructionSet = VMRuntime.getInstructionSet(abi);
             if (!completedIsas.contains(instructionSet)) {
                 try {
@@ -7397,7 +7421,7 @@
                 userId = UserHandle.USER_CURRENT;
             }
             try {
-                if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+                if (callingUid != 0 && callingUid != SYSTEM_UID) {
                     final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
                             MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
                     if (!UserHandle.isSameApp(callingUid, uid)) {
@@ -7834,7 +7858,7 @@
                     return false;
                 }
                 // An activity is consider to be in multi-window mode if its task isn't fullscreen.
-                return !r.task.mFullscreen;
+                return !r.getTask().mFullscreen;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -8664,7 +8688,7 @@
         // Third...  does the caller itself have permission to access
         // this uri?
         final int callingAppId = UserHandle.getAppId(callingUid);
-        if ((callingAppId == Process.SYSTEM_UID) || (callingAppId == Process.ROOT_UID)) {
+        if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
             if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
                 // Exempted authority for cropping user photos in Settings app
             } else {
@@ -9150,7 +9174,7 @@
                 throw new IllegalArgumentException("Unknown owner: " + token);
             }
             if (fromUid != Binder.getCallingUid()) {
-                if (Binder.getCallingUid() != Process.myUid()) {
+                if (Binder.getCallingUid() != myUid()) {
                     // Only system code can grant URI permissions on behalf
                     // of other users.
                     throw new SecurityException("nice try");
@@ -9534,8 +9558,8 @@
     public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
         final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
         final long cachedAppMem = mProcessList.getMemLevel(ProcessList.CACHED_APP_MIN_ADJ);
-        outInfo.availMem = Process.getFreeMemory();
-        outInfo.totalMem = Process.getTotalMemory();
+        outInfo.availMem = getFreeMemory();
+        outInfo.totalMem = getTotalMemory();
         outInfo.threshold = homeAppMem;
         outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((cachedAppMem-homeAppMem)/2));
         outInfo.hiddenAppThreshold = cachedAppMem;
@@ -9927,8 +9951,9 @@
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
                 r.setTaskDescription(td);
-                r.task.updateTaskDescription();
-                mTaskChangeNotificationController.notifyTaskDescriptionChanged(r.task.taskId, td);
+                final TaskRecord task = r.getTask();
+                task.updateTaskDescription();
+                mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
             }
         }
     }
@@ -10378,8 +10403,8 @@
                 }
 
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
-                r.task.reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT,
-                        ANIMATE, !DEFER_RESUME, "exitFreeformMode");
+                r.getTask().reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
+                        REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "exitFreeformMode");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -10677,7 +10702,7 @@
     @Override
     public void updateDeviceOwner(String packageName) {
         final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+        if (callingUid != 0 && callingUid != SYSTEM_UID) {
             throw new SecurityException("updateDeviceOwner called from non-system process");
         }
         synchronized (this) {
@@ -10688,7 +10713,7 @@
     @Override
     public void updateLockTaskPackages(int userId, String[] packages) {
         final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
+        if (callingUid != 0 && callingUid != SYSTEM_UID) {
             enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
                     "updateLockTaskPackages()");
         }
@@ -10711,7 +10736,7 @@
         // is initiated by system after the pinning request was shown and locked mode is initiated
         // by an authorized app directly
         final int callingUid = Binder.getCallingUid();
-        boolean isSystemInitiated = callingUid == Process.SYSTEM_UID;
+        boolean isSystemInitiated = callingUid == SYSTEM_UID;
         long ident = Binder.clearCallingIdentity();
         try {
             if (!isSystemInitiated) {
@@ -10760,7 +10785,7 @@
             if (r == null) {
                 return;
             }
-            final TaskRecord task = r.task;
+            final TaskRecord task = r.getTask();
             if (task != null) {
                 startLockTaskModeLocked(task);
             }
@@ -10859,7 +10884,7 @@
             if (r == null) {
                 return;
             }
-            mStackSupervisor.showLockTaskEscapeMessageLocked(r.task);
+            mStackSupervisor.showLockTaskEscapeMessageLocked(r.getTask());
         }
     }
 
@@ -11190,7 +11215,7 @@
             proc.procStatFile = "/proc/" + proc.pid + "/stat";
         }
         mProcessStateStatsLongs[0] = 0;
-        if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+        if (!readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
                 mProcessStateStatsLongs, null)) {
             if (DEBUG_OOM_ADJ) Slog.d(TAG, "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
             return false;
@@ -11892,7 +11917,7 @@
     public final void installSystemProviders() {
         List<ProviderInfo> providers;
         synchronized (this) {
-            ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
+            ProcessRecord app = mProcessNames.get("system", SYSTEM_UID);
             providers = generateApplicationProvidersLocked(app);
             if (providers != null) {
                 for (int i=providers.size()-1; i>=0; i--) {
@@ -12065,11 +12090,11 @@
         int uid = info.uid;
         if (isolated) {
             if (isolatedUid == 0) {
-                int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
+                int stepsLeft = LAST_ISOLATED_UID - FIRST_ISOLATED_UID + 1;
                 while (true) {
-                    if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID
-                            || mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) {
-                        mNextIsolatedProcessUid = Process.FIRST_ISOLATED_UID;
+                    if (mNextIsolatedProcessUid < FIRST_ISOLATED_UID
+                            || mNextIsolatedProcessUid > LAST_ISOLATED_UID) {
+                        mNextIsolatedProcessUid = FIRST_ISOLATED_UID;
                     }
                     uid = UserHandle.getUid(userId, mNextIsolatedProcessUid);
                     mNextIsolatedProcessUid++;
@@ -13121,9 +13146,10 @@
                 if (r == null) {
                     return false;
                 }
-                int index = r.task.mActivities.lastIndexOf(r);
+                final TaskRecord task = r.getTask();
+                int index = task.mActivities.lastIndexOf(r);
                 if (index > 0) {
-                    ActivityRecord under = r.task.mActivities.get(index - 1);
+                    ActivityRecord under = task.mActivities.get(index - 1);
                     under.returningOptions = ActivityOptions.fromBundle(options);
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(false);
@@ -13257,7 +13283,7 @@
         synchronized (this) {
             // Disable any existing VR thread.
             if (mTopAppVrThreadTid > 0) {
-                Process.setThreadScheduler(mTopAppVrThreadTid, Process.SCHED_OTHER, 0);
+                setThreadScheduler(mTopAppVrThreadTid, SCHED_OTHER, 0);
                 mTopAppVrThreadTid = 0;
             }
 
@@ -13281,15 +13307,15 @@
      */
     private int updateVrThreadLocked(ProcessRecord proc, int lastTid, int pid, int tid) {
         // ensure the tid belongs to the process
-        if (!Process.isThreadInProcess(pid, tid)) {
+        if (!isThreadInProcess(pid, tid)) {
             throw new IllegalArgumentException("VR thread does not belong to process");
         }
 
         // reset existing VR thread to CFS if this thread still exists and belongs to
         // the calling process
-        if (lastTid != 0 && Process.isThreadInProcess(pid, lastTid)) {
+        if (lastTid != 0 && isThreadInProcess(pid, lastTid)) {
             try {
-                Process.setThreadScheduler(lastTid, Process.SCHED_OTHER, 0);
+                setThreadScheduler(lastTid, SCHED_OTHER, 0);
             } catch (IllegalArgumentException e) {
                 // Ignore this.  Only occurs in race condition where previous VR thread
                 // was destroyed during this method call.
@@ -13300,8 +13326,8 @@
         try {
             if ((proc == null || proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP)
                     && tid > 0) {
-                Process.setThreadScheduler(tid,
-                    Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                setThreadScheduler(tid,
+                    SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
             }
             return tid;
         } catch (IllegalArgumentException e) {
@@ -13320,7 +13346,7 @@
                 proc = mPidsSelfLocked.get(pid);
                 if (proc != null && proc.renderThreadTid == 0 && tid > 0) {
                     // ensure the tid belongs to the process
-                    if (!Process.isThreadInProcess(pid, tid)) {
+                    if (!isThreadInProcess(pid, tid)) {
                         throw new IllegalArgumentException(
                             "Render thread does not belong to process");
                     }
@@ -13332,10 +13358,10 @@
                     if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
                         if (DEBUG_OOM_ADJ) Slog.d("UI_FIFO", "Promoting " + tid + "out of band");
                         if (mUseFifoUiScheduling) {
-                            Process.setThreadScheduler(proc.renderThreadTid,
-                                Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                            setThreadScheduler(proc.renderThreadTid,
+                                SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
                         } else {
-                            Process.setThreadPriority(proc.renderThreadTid, -10);
+                            setThreadPriority(proc.renderThreadTid, -10);
                         }
                     }
                 } else {
@@ -13410,7 +13436,7 @@
             if (r == null) {
                 throw new IllegalArgumentException();
             }
-            return r.task.getTopActivity() == r;
+            return r.getTask().getTopActivity() == r;
         }
     }
 
@@ -13496,7 +13522,7 @@
                 if (sender == null) {
                     uid = sourceUid;
                 } else {
-                    uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+                    uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
                 }
                 BatteryStatsImpl.Uid.Pkg pkg =
                     stats.getPackageStatsLocked(sourceUid >= 0 ? sourceUid : uid,
@@ -13519,7 +13545,7 @@
             if (sender == null) {
                 uid = sourceUid;
             } else {
-                uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+                uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
             }
             mBatteryStatsService.noteAlarmStart(tag, sourceUid >= 0 ? sourceUid : uid);
         }
@@ -13538,14 +13564,14 @@
             if (sender == null) {
                 uid = sourceUid;
             } else {
-                uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
+                uid = rec.uid == MY_UID ? SYSTEM_UID : rec.uid;
             }
             mBatteryStatsService.noteAlarmFinish(tag, sourceUid >= 0 ? sourceUid : uid);
         }
     }
 
     public boolean killPids(int[] pids, String pReason, boolean secure) {
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+        if (Binder.getCallingUid() != SYSTEM_UID) {
             throw new SecurityException("killPids only available to the system");
         }
         String reason = (pReason == null) ? "Unknown" : pReason;
@@ -13611,7 +13637,7 @@
 
     @Override
     public boolean killProcessesBelowForeground(String reason) {
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+        if (Binder.getCallingUid() != SYSTEM_UID) {
             throw new SecurityException("killProcessesBelowForeground() only available to system");
         }
 
@@ -13619,7 +13645,7 @@
     }
 
     private boolean killProcessesBelowAdj(int belowAdj, String reason) {
-        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+        if (Binder.getCallingUid() != SYSTEM_UID) {
             throw new SecurityException("killProcessesBelowAdj() only available to system");
         }
 
@@ -13696,7 +13722,7 @@
                 Log.i(TAG, "Shutting down activity manager...");
                 shutdown(10000);
                 Log.i(TAG, "Shutdown complete, restarting!");
-                Process.killProcess(Process.myPid());
+                killProcess(myPid());
                 System.exit(10);
             }
         };
@@ -14040,7 +14066,7 @@
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
                 broadcastIntentLocked(null, null, intent,
                         null, null, 0, null, null, null, AppOpsManager.OP_NONE,
-                        null, false, false, MY_PID, Process.SYSTEM_UID,
+                        null, false, false, MY_PID, SYSTEM_UID,
                         currentUserId);
                 intent = new Intent(Intent.ACTION_USER_STARTING);
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -14054,7 +14080,7 @@
                             }
                         }, 0, null, null,
                         new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
-                        null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+                        null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
             } catch (Throwable t) {
                 Slog.wtf(TAG, "Failed sending first user broadcasts", t);
             } finally {
@@ -15928,8 +15954,9 @@
             }
             needSep = true;
             synchronized (this) {
-                if (lastTask != r.task) {
-                    lastTask = r.task;
+                final TaskRecord task = r.getTask();
+                if (lastTask != task) {
+                    lastTask = task;
                     pw.print("TASK "); pw.print(lastTask.affinity);
                             pw.print(" id="); pw.print(lastTask.taskId);
                             pw.print(" userId="); pw.println(lastTask.userId);
@@ -16698,22 +16725,22 @@
     private final long[] getKsmInfo() {
         long[] longOut = new long[4];
         final int[] SINGLE_LONG_FORMAT = new int[] {
-            Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
+            PROC_SPACE_TERM| PROC_OUT_LONG
         };
         long[] longTmp = new long[1];
-        Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
+        readProcFile("/sys/kernel/mm/ksm/pages_shared",
                 SINGLE_LONG_FORMAT, null, longTmp, null);
         longOut[KSM_SHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
         longTmp[0] = 0;
-        Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
+        readProcFile("/sys/kernel/mm/ksm/pages_sharing",
                 SINGLE_LONG_FORMAT, null, longTmp, null);
         longOut[KSM_SHARING] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
         longTmp[0] = 0;
-        Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
+        readProcFile("/sys/kernel/mm/ksm/pages_unshared",
                 SINGLE_LONG_FORMAT, null, longTmp, null);
         longOut[KSM_UNSHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
         longTmp[0] = 0;
-        Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
+        readProcFile("/sys/kernel/mm/ksm/pages_volatile",
                 SINGLE_LONG_FORMAT, null, longTmp, null);
         longOut[KSM_VOLATILE] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
         return longOut;
@@ -17989,7 +18016,7 @@
             String className, int flags) {
         boolean result = false;
         // For apps that don't have pre-defined UIDs, check for permission
-        if (UserHandle.getAppId(aInfo.uid) >= Process.FIRST_APPLICATION_UID) {
+        if (UserHandle.getAppId(aInfo.uid) >= FIRST_APPLICATION_UID) {
             if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
                 if (ActivityManager.checkUidPermission(
                         INTERACT_ACROSS_USERS,
@@ -18008,7 +18035,7 @@
             result = true;
         } else if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
             // Phone app and persistent apps are allowed to export singleuser providers.
-            result = UserHandle.isSameApp(aInfo.uid, Process.PHONE_UID)
+            result = UserHandle.isSameApp(aInfo.uid, PHONE_UID)
                     || (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0;
         }
         if (DEBUG_MU) Slog.v(TAG_MU,
@@ -18026,8 +18053,8 @@
     boolean isValidSingletonCall(int callingUid, int componentUid) {
         int componentAppId = UserHandle.getAppId(componentUid);
         return UserHandle.isSameApp(callingUid, componentUid)
-                || componentAppId == Process.SYSTEM_UID
-                || componentAppId == Process.PHONE_UID
+                || componentAppId == SYSTEM_UID
+                || componentAppId == PHONE_UID
                 || ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, componentUid)
                         == PackageManager.PERMISSION_GRANTED;
     }
@@ -18268,7 +18295,7 @@
     // =========================================================
 
     private boolean isInstantApp(ProcessRecord record, String callerPackage, int uid) {
-        if (UserHandle.getAppId(uid) < Process.FIRST_APPLICATION_UID) {
+        if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) {
             return false;
         }
         // Easy case -- we have the app's ProcessRecord.
@@ -18329,7 +18356,7 @@
                             + " (pid=" + Binder.getCallingPid()
                             + ") when registering receiver " + receiver);
                 }
-                if (callerApp.info.uid != Process.SYSTEM_UID &&
+                if (callerApp.info.uid != SYSTEM_UID &&
                         !callerApp.pkgList.containsKey(callerPackage) &&
                         !"android".equals(callerPackage)) {
                     throw new SecurityException("Given caller package " + callerPackage
@@ -18546,7 +18573,7 @@
             for (int user : users) {
                 // Skip users that have Shell restrictions, with exception of always permitted
                 // Shell broadcasts
-                if (callingUid == Process.SHELL_UID
+                if (callingUid == SHELL_UID
                         && mUserController.hasUserRestriction(
                                 UserManager.DISALLOW_DEBUGGING_FEATURES, user)
                         && !isPermittedShellBroadcast(intent)) {
@@ -18730,7 +18757,7 @@
         // and upgrade steps.
 
         if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
-            if ((callingUid != Process.SYSTEM_UID
+            if ((callingUid != SYSTEM_UID
                     || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
                     && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
                 Slog.w(TAG, "Skipping broadcast of " + intent
@@ -18774,11 +18801,11 @@
 
         final boolean isCallerSystem;
         switch (UserHandle.getAppId(callingUid)) {
-            case Process.ROOT_UID:
-            case Process.SYSTEM_UID:
-            case Process.PHONE_UID:
-            case Process.BLUETOOTH_UID:
-            case Process.NFC_UID:
+            case ROOT_UID:
+            case SYSTEM_UID:
+            case PHONE_UID:
+            case BLUETOOTH_UID:
+            case NFC_UID:
                 isCallerSystem = true;
                 break;
             default:
@@ -19154,7 +19181,7 @@
             receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
         }
         if (intent.getComponent() == null) {
-            if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
+            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                 // Query one target user at a time, excluding shell-restricted users
                 for (int i = 0; i < users.length; i++) {
                     if (mUserController.hasUserRestriction(
@@ -19396,8 +19423,8 @@
 
         if ((flags & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
             switch (Binder.getCallingUid()) {
-                case Process.ROOT_UID:
-                case Process.SHELL_UID:
+                case ROOT_UID:
+                case SHELL_UID:
                     break;
                 default:
                     Slog.w(TAG, "Removing FLAG_RECEIVER_FROM_SHELL because caller is UID "
@@ -19852,7 +19879,7 @@
 
     private void enforceWriteSettingsPermission(String func) {
         int uid = Binder.getCallingUid();
-        if (uid == Process.ROOT_UID) {
+        if (uid == ROOT_UID) {
             return;
         }
 
@@ -20050,7 +20077,7 @@
                 | Intent.FLAG_RECEIVER_FOREGROUND
                 | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
         broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
-                AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+                AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
                 UserHandle.USER_ALL);
         if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
             intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
@@ -20061,7 +20088,7 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             }
             broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
-                    AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
+                    AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
                     UserHandle.USER_ALL);
         }
 
@@ -20561,8 +20588,9 @@
                     app.cached = false;
                     app.empty = false;
                     foregroundActivities = true;
-                    if (r.task != null && minLayer > 0) {
-                        final int layer = r.task.mLayerRank;
+                    final TaskRecord task = r.getTask();
+                    if (task != null && minLayer > 0) {
+                        final int layer = task.mLayerRank;
                         if (layer >= 0 && minLayer > layer) {
                             minLayer = layer;
                         }
@@ -21534,27 +21562,27 @@
                 int processGroup;
                 switch (app.curSchedGroup) {
                     case ProcessList.SCHED_GROUP_BACKGROUND:
-                        processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+                        processGroup = THREAD_GROUP_BG_NONINTERACTIVE;
                         break;
                     case ProcessList.SCHED_GROUP_TOP_APP:
                     case ProcessList.SCHED_GROUP_TOP_APP_BOUND:
-                        processGroup = Process.THREAD_GROUP_TOP_APP;
+                        processGroup = THREAD_GROUP_TOP_APP;
                         break;
                     default:
-                        processGroup = Process.THREAD_GROUP_DEFAULT;
+                        processGroup = THREAD_GROUP_DEFAULT;
                         break;
                 }
                 long oldId = Binder.clearCallingIdentity();
                 try {
-                    Process.setProcessGroup(app.pid, processGroup);
+                    setProcessGroup(app.pid, processGroup);
                     if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
                         // do nothing if we already switched to RT
                         if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
                             // Switch VR thread for app to SCHED_FIFO
                             if (mVrState == VR_MODE && app.vrThreadTid != 0) {
                                 try {
-                                    Process.setThreadScheduler(app.vrThreadTid,
-                                        Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                    setThreadScheduler(app.vrThreadTid,
+                                        SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
                                     mTopAppVrThreadTid = app.vrThreadTid;
                                 } catch (IllegalArgumentException e) {
                                     // thread died, ignore
@@ -21562,17 +21590,17 @@
                             }
                             if (mUseFifoUiScheduling) {
                                 // Switch UI pipeline for app to SCHED_FIFO
-                                app.savedPriority = Process.getThreadPriority(app.pid);
+                                app.savedPriority = getThreadPriority(app.pid);
                                 try {
-                                    Process.setThreadScheduler(app.pid,
-                                        Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                    setThreadScheduler(app.pid,
+                                        SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
                                 } catch (IllegalArgumentException e) {
                                     // thread died, ignore
                                 }
                                 if (app.renderThreadTid != 0) {
                                     try {
-                                        Process.setThreadScheduler(app.renderThreadTid,
-                                            Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1);
+                                        setThreadScheduler(app.renderThreadTid,
+                                            SCHED_FIFO | SCHED_RESET_ON_FORK, 1);
                                     } catch (IllegalArgumentException e) {
                                         // thread died, ignore
                                     }
@@ -21587,10 +21615,10 @@
                                 }
                             } else {
                                 // Boost priority for top app UI and render threads
-                                Process.setThreadPriority(app.pid, -10);
+                                setThreadPriority(app.pid, -10);
                                 if (app.renderThreadTid != 0) {
                                     try {
-                                        Process.setThreadPriority(app.renderThreadTid, -10);
+                                        setThreadPriority(app.renderThreadTid, -10);
                                     } catch (IllegalArgumentException e) {
                                         // thread died, ignore
                                     }
@@ -21602,23 +21630,23 @@
                         // Reset VR thread to SCHED_OTHER
                         // Safe to do even if we're not in VR mode
                         if (app.vrThreadTid != 0) {
-                            Process.setThreadScheduler(app.vrThreadTid, Process.SCHED_OTHER, 0);
+                            setThreadScheduler(app.vrThreadTid, SCHED_OTHER, 0);
                             mTopAppVrThreadTid = 0;
                         }
                         if (mUseFifoUiScheduling) {
                             // Reset UI pipeline to SCHED_OTHER
-                            Process.setThreadScheduler(app.pid, Process.SCHED_OTHER, 0);
-                            Process.setThreadPriority(app.pid, app.savedPriority);
+                            setThreadScheduler(app.pid, SCHED_OTHER, 0);
+                            setThreadPriority(app.pid, app.savedPriority);
                             if (app.renderThreadTid != 0) {
-                                Process.setThreadScheduler(app.renderThreadTid,
-                                    Process.SCHED_OTHER, 0);
-                                Process.setThreadPriority(app.renderThreadTid, -4);
+                                setThreadScheduler(app.renderThreadTid,
+                                    SCHED_OTHER, 0);
+                                setThreadPriority(app.renderThreadTid, -4);
                             }
                         } else {
                             // Reset priority for top app UI and render threads
-                            Process.setThreadPriority(app.pid, 0);
+                            setThreadPriority(app.pid, 0);
                             if (app.renderThreadTid != 0) {
-                                Process.setThreadPriority(app.renderThreadTid, 0);
+                                setThreadPriority(app.renderThreadTid, 0);
                             }
                         }
                     }
@@ -22728,7 +22756,7 @@
 
     /** This method sends the specified signal to each of the persistent apps */
     public void signalPersistentProcesses(int sig) throws RemoteException {
-        if (sig != Process.SIGNAL_USR1) {
+        if (sig != SIGNAL_USR1) {
             throw new SecurityException("Only SIGNAL_USR1 is allowed");
         }
 
@@ -22742,7 +22770,7 @@
             for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
                 ProcessRecord r = mLruProcesses.get(i);
                 if (r.thread != null && r.persistent) {
-                    Process.sendSignal(r.pid, sig);
+                    sendSignal(r.pid, sig);
                 }
             }
         }
@@ -23883,7 +23911,7 @@
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             final ProcessRecord app = mLruProcesses.get(i);
-            if (app.thread == null || app.pid == Process.myPid()) {
+            if (app.thread == null) {
                 continue;
             }
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index cbb51e1..3a29414 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -229,7 +229,7 @@
     private int theme;              // resource identifier of activity's theme.
     private int realTheme;          // actual theme resource we will use, never 0.
     private int windowFlags;        // custom window flags for preview window.
-    TaskRecord task;        // the task this is in.
+    private TaskRecord task;        // the task this is in.
     private long createTime = System.currentTimeMillis();
     long displayStartTime;  // when we started launching this activity
     long fullyDrawnStartTime; // when we started launching this activity
@@ -686,9 +686,48 @@
 
     @Override
     protected ConfigurationContainer getParent() {
+        return getTask();
+    }
+
+    TaskRecord getTask() {
         return task;
     }
 
+    /**
+     * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
+     * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
+     * children. However, this method will clean up references to this {@link ActivityRecord} in
+     * {@link ActivityStack}.
+     * @param task The new parent {@link TaskRecord}.
+     */
+    void setTask(TaskRecord task) {
+        setTask(task, false /*reparenting*/);
+    }
+
+    /**
+     * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
+     */
+    void setTask(TaskRecord task, boolean reparenting) {
+        // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}.
+        if (task != null && task == getTask()) {
+            return;
+        }
+
+        final ActivityStack stack = getStack();
+
+        // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
+        // {@link ActivityRecord} from its current {@link ActivityStack}.
+        if (!reparenting && stack != null && (task == null || stack != task.getStack())) {
+            stack.onActivityRemovedFromStack(this);
+        }
+
+        this.task = task;
+
+        if (!reparenting) {
+            onParentChanged();
+        }
+    }
+
     static class Token extends IApplicationToken.Stub {
         private final WeakReference<ActivityRecord> weakActivity;
 
@@ -925,8 +964,8 @@
         // Must reparent first in window manager
         mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
 
-        // Remove the activity from the old task and add it to the new task
-        prevTask.removeActivity(this);
+        // Remove the activity from the old task and add it to the new task.
+        prevTask.removeActivity(this, true /*reparenting*/);
 
         newTask.addActivityAtIndex(position, this);
     }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ee37463..f13b11e 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -116,6 +116,7 @@
 import android.util.SparseArray;
 import android.view.Display;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.Watchdog;
@@ -725,7 +726,7 @@
         if (r == null) {
             return null;
         }
-        final TaskRecord task = r.task;
+        final TaskRecord task = r.getTask();
         final ActivityStack stack = r.getStack();
         if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
             if (stack != this) Slog.w(TAG,
@@ -934,7 +935,7 @@
 
             if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
                     + taskIntent.getComponent().flattenToShortString()
-                    + "/aff=" + r.task.rootAffinity + " to new cls="
+                    + "/aff=" + r.getTask().rootAffinity + " to new cls="
                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
             // TODO Refactor to remove duplications. Check if logic can be simplified.
             if (taskIntent != null && taskIntent.getComponent() != null &&
@@ -1049,8 +1050,9 @@
 
     void addRecentActivityLocked(ActivityRecord r) {
         if (r != null) {
-            mRecentTasks.addLocked(r.task);
-            r.task.touchActiveTime();
+            final TaskRecord task = r.getTask();
+            mRecentTasks.addLocked(task);
+            task.touchActiveTime();
         }
     }
 
@@ -1226,11 +1228,12 @@
         mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
         prev.state = ActivityState.PAUSING;
-        prev.task.touchActiveTime();
+        prev.getTask().touchActiveTime();
         clearLaunchTime(prev);
         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
         if (mService.mHasRecents
-                && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
+                && (next == null || next.noDisplay || next.getTask() != prev.getTask()
+                || uiSleeping)) {
             prev.mUpdateTaskThumbnailWhenHidden = true;
         }
         stopFullyDrawnTraceIfNeeded();
@@ -1457,7 +1460,7 @@
     // Find the first visible activity above the passed activity and if it is translucent return it
     // otherwise return null;
     ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
-        TaskRecord task = r.task;
+        TaskRecord task = r.getTask();
         if (task == null) {
             return null;
         }
@@ -1604,7 +1607,7 @@
             // Otherwise, the docked stack is always visible, except in the case where the top
             // running activity task in the focus stack doesn't support any form of resizing but we
             // show it for the home task even though it's not resizable.
-            final TaskRecord task = r != null ? r.task : null;
+            final TaskRecord task = r != null ? r.getTask() : null;
             return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
                     : STACK_INVISIBLE;
         }
@@ -2157,8 +2160,9 @@
         mResumedActivity = r;
         r.state = ActivityState.RESUMED;
         mService.setResumedActivityUncheckLocked(r, reason);
-        r.task.touchActiveTime();
-        mRecentTasks.addLocked(r.task);
+        final TaskRecord task = r.getTask();
+        task.touchActiveTime();
+        mRecentTasks.addLocked(task);
     }
 
     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -2207,8 +2211,8 @@
             return false;
         }
 
-        final TaskRecord nextTask = next.task;
-        final TaskRecord prevTask = prev != null ? prev.task : null;
+        final TaskRecord nextTask = next.getTask();
+        final TaskRecord prevTask = prev != null ? prev.getTask() : null;
         if (prevTask != null && prevTask.getStack() == this &&
                 prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
@@ -2373,7 +2377,7 @@
                     anim = false;
                     mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                 } else {
-                    mWindowManager.prepareAppTransition(prev.task == next.task
+                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                             ? TRANSIT_ACTIVITY_CLOSE
                             : TRANSIT_TASK_CLOSE, false);
                 }
@@ -2385,7 +2389,7 @@
                     anim = false;
                     mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                 } else {
-                    mWindowManager.prepareAppTransition(prev.task == next.task
+                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                             ? TRANSIT_ACTIVITY_OPEN
                             : next.mLaunchTaskBehind
                                     ? TRANSIT_TASK_OPEN_BEHIND
@@ -2522,7 +2526,8 @@
                 next.notifyAppResumed(next.stopped, allowSavedSurface);
 
                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
-                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);
+                        System.identityHashCode(next), next.getTask().taskId,
+                        next.shortComponentName);
 
                 next.sleeping = false;
                 mService.showUnsupportedZoomDialogIfNeededLocked(next);
@@ -2696,9 +2701,15 @@
             return;
         }
 
-        // If the task was launched from the assistant stack, set the return type to assistant
         final ActivityStack lastStack = mStackSupervisor.getLastStack();
-        if (lastStack != null && lastStack.isAssistantStack()) {
+
+        // If there is no last task, do not set task to return to
+        if (lastStack == null) {
+            return;
+        }
+
+        // If the task was launched from the assistant stack, set the return type to assistant
+        if (lastStack.isAssistantStack()) {
             task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
             return;
         }
@@ -2721,7 +2732,7 @@
 
     final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
             boolean newTask, boolean keepCurTransition, ActivityOptions options) {
-        TaskRecord rTask = r.task;
+        TaskRecord rTask = r.getTask();
         final int taskId = rTask.taskId;
         // mLaunchTaskBehind tasks get placed at the back of the task stack.
         if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
@@ -2740,7 +2751,7 @@
                     // All activities in task are finishing.
                     continue;
                 }
-                if (task == r.task) {
+                if (task == rTask) {
                     // Here it is!  Now, if this is not yet visible to the
                     // user, then just add it without starting; it will
                     // get started when the user navigates back to it.
@@ -2762,13 +2773,14 @@
 
         // If we are not placing the new activity frontmost, we do not want to deliver the
         // onUserLeaving callback to the actual frontmost activity
-        if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
+        final TaskRecord activityTask = r.getTask();
+        if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
             mStackSupervisor.mUserLeaving = false;
             if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                     "startActivity() behind front, mUserLeaving=false");
         }
 
-        task = r.task;
+        task = activityTask;
 
         // Slot the activity into the history stack and proceed
         if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
@@ -2795,7 +2807,8 @@
                     } else {
                         // If a new task is being launched, then mark the existing top activity as
                         // supporting picture-in-picture while pausing
-                        if (focusedTopActivity != null) {
+                        if (focusedTopActivity != null &&
+                                focusedTopActivity.getStack().getStackId() != PINNED_STACK_ID) {
                             focusedTopActivity.supportsPictureInPictureWhilePausing = true;
                         }
                         transit = TRANSIT_TASK_OPEN;
@@ -2829,11 +2842,12 @@
                 // "has the same starting icon" as the next one.  This allows the
                 // window manager to keep the previous window it had previously
                 // created, if it still had one.
-                ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
+                TaskRecord prevTask = r.getTask();
+                ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
                 if (prev != null) {
                     // We don't want to reuse the previous starting preview if:
                     // (1) The current activity is in a different task.
-                    if (prev.task != r.task) {
+                    if (prev.getTask() != prevTask) {
                         prev = null;
                     }
                     // (2) The current activity is already displayed.
@@ -2852,7 +2866,7 @@
 
     private boolean isTaskSwitch(ActivityRecord r,
             ActivityRecord topFocusedActivity) {
-        return topFocusedActivity != null && r.task != topFocusedActivity.task;
+        return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
     }
 
     /**
@@ -2919,20 +2933,20 @@
                         !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
                                 mTaskHistory.get(0).mActivities.get(0) : null;
                 if (bottom != null && target.taskAffinity != null
-                        && target.taskAffinity.equals(bottom.task.affinity)) {
+                        && target.taskAffinity.equals(bottom.getTask().affinity)) {
                     // If the activity currently at the bottom has the
                     // same task affinity as the one we are moving,
                     // then merge it into the same task.
-                    targetTask = bottom.task;
+                    targetTask = bottom.getTask();
                     if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
-                            + " out to bottom task " + bottom.task);
+                            + " out to bottom task " + targetTask);
                 } else {
                     targetTask = createTaskRecord(
                             mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
                             target.info, null, null, null, false, target.mActivityType);
                     targetTask.affinityIntent = target.intent;
                     if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
-                            + " out to new task " + target.task);
+                            + " out to new task " + targetTask);
                 }
 
                 boolean noOptions = canMoveOptions;
@@ -2954,7 +2968,7 @@
                             "Removing activity " + p + " from task=" + task + " adding to task="
                             + targetTask + " Callers=" + Debug.getCallers(4));
                     if (DEBUG_TASKS) Slog.v(TAG_TASKS,
-                            "Pushing next activity " + p + " out to target's task " + target.task);
+                            "Pushing next activity " + p + " out to target's task " + target);
                     p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
                 }
 
@@ -3125,13 +3139,13 @@
         boolean forceReset =
                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
         if (ACTIVITY_INACTIVE_RESET_TIME > 0
-                && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
+                && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
             if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
                 forceReset = true;
             }
         }
 
-        final TaskRecord task = taskTop.task;
+        final TaskRecord task = taskTop.getTask();
 
         /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
          * for remaining tasks. Used for later tasks to reparent to task. */
@@ -3214,7 +3228,7 @@
                 // stack as long as there is a running activity.
                 return;
             } else {
-                final TaskRecord task = r.task;
+                final TaskRecord task = r.getTask();
                 final boolean isAssistantOrOverAssistant = task.getStack().isAssistantStack() ||
                         task.isOverAssistantStack();
                 if (r.frontOfTask && task == topTask() &&
@@ -3373,10 +3387,12 @@
         }
         Slog.w(TAG, "  Force finishing activity "
                 + r.intent.getComponent().flattenToShortString());
-        int taskNdx = mTaskHistory.indexOf(r.task);
-        int activityNdx = r.task.mActivities.indexOf(r);
+        finishedTask = r.getTask();
+        int taskNdx = mTaskHistory.indexOf(finishedTask);
+        final TaskRecord task = finishedTask;
+        int activityNdx = task.mActivities.indexOf(r);
         finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
-        finishedTask = r.task;
+        finishedTask = task;
         // Also terminate any activities below it that aren't yet
         // stopped, to avoid a situation where one will get
         // re-start our crashing activity once it gets resumed again.
@@ -3446,7 +3462,7 @@
     }
 
     final boolean finishActivityAffinityLocked(ActivityRecord r) {
-        ArrayList<ActivityRecord> activities = r.task.mActivities;
+        ArrayList<ActivityRecord> activities = r.getTask().mActivities;
         for (int index = activities.indexOf(r); index >= 0; --index) {
             ActivityRecord cur = activities.get(index);
             if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
@@ -3511,7 +3527,7 @@
         mWindowManager.deferSurfaceLayout();
         try {
             r.makeFinishingLocked();
-            final TaskRecord task = r.task;
+            final TaskRecord task = r.getTask();
             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                     r.userId, System.identityHashCode(r),
                     task.taskId, r.shortComponentName, reason);
@@ -3700,23 +3716,24 @@
     final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
         // Basic case: for simple app-centric recents, we need to recreate
         // the task if the affinity has changed.
-        if (srec == null || srec.task.affinity == null ||
-                !srec.task.affinity.equals(destAffinity)) {
+        if (srec == null || srec.getTask().affinity == null ||
+                !srec.getTask().affinity.equals(destAffinity)) {
             return true;
         }
         // Document-centric case: an app may be split in to multiple documents;
         // they need to re-create their task if this current activity is the root
         // of a document, unless simply finishing it will return them to the the
         // correct app behind.
-        if (srec.frontOfTask && srec.task != null && srec.task.getBaseIntent() != null
-                && srec.task.getBaseIntent().isDocument()) {
+        final TaskRecord task = srec.getTask();
+        if (srec.frontOfTask && task != null && task.getBaseIntent() != null
+                && task.getBaseIntent().isDocument()) {
             // Okay, this activity is at the root of its task.  What to do, what to do...
-            if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
+            if (task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
                 // Finishing won't return to an application, so we need to recreate.
                 return true;
             }
             // We now need to get the task below it to determine what to do.
-            int taskIdx = mTaskHistory.indexOf(srec.task);
+            int taskIdx = mTaskHistory.indexOf(task);
             if (taskIdx <= 0) {
                 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
                 return false;
@@ -3726,7 +3743,7 @@
                 return true;
             }
             TaskRecord prevTask = mTaskHistory.get(taskIdx);
-            if (!srec.task.affinity.equals(prevTask.affinity)) {
+            if (!task.affinity.equals(prevTask.affinity)) {
                 // These are different apps, so need to recreate.
                 return true;
             }
@@ -3736,7 +3753,7 @@
 
     final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
             Intent resultData) {
-        final TaskRecord task = srec.task;
+        final TaskRecord task = srec.getTask();
         final ArrayList<ActivityRecord> activities = task.mActivities;
         final int start = activities.indexOf(srec);
         if (!mTaskHistory.contains(task) || (start < 0)) {
@@ -3815,6 +3832,22 @@
         Binder.restoreCallingIdentity(origId);
         return foundParentInTask;
     }
+
+    /**
+     * Remove any state associated with the {@link ActivityRecord}. This should be called whenever
+     * an activity moves away from the stack.
+     */
+    void onActivityRemovedFromStack(ActivityRecord r) {
+        if (mResumedActivity == r) {
+            mResumedActivity = null;
+        }
+        if (mPausingActivity == r) {
+            mPausingActivity = null;
+        }
+
+        removeTimeoutsForActivityLocked(r);
+    }
+
     /**
      * Perform the common clean-up of an activity record.  This is called both
      * as part of destroyActivityLocked() (when destroying the client-side
@@ -3825,12 +3858,7 @@
      * Note: Call before #removeActivityFromHistoryLocked.
      */
     private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
-        if (mResumedActivity == r) {
-            mResumedActivity = null;
-        }
-        if (mPausingActivity == r) {
-            mPausingActivity = null;
-        }
+        onActivityRemovedFromStack(r);
 
         r.deferRelaunchUntilPaused = false;
         r.frozenBeforeDestroy = false;
@@ -3897,7 +3925,7 @@
         if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
         r.app = null;
         r.removeWindowContainer();
-        final TaskRecord task = r.task;
+        final TaskRecord task = r.getTask();
         final boolean lastActivity = task != null ? task.removeActivity(r) : false;
         // If we are removing the last activity in the task, not including task overlay activities,
         // then fall through into the block below to remove the entire task itself
@@ -4043,7 +4071,7 @@
                         + ", app=" + (r.app != null ? r.app.processName : "(null)"));
         EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
                 r.userId, System.identityHashCode(r),
-                r.task.taskId, r.shortComponentName, reason);
+                r.getTask().taskId, r.shortComponentName, reason);
 
         boolean removedFromHistory = false;
 
@@ -4275,7 +4303,7 @@
                             Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
                             EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                                     r.userId, System.identityHashCode(r),
-                                    r.task.taskId, r.shortComponentName,
+                                    r.getTask().taskId, r.shortComponentName,
                                     "proc died without state saved");
                             if (r.state == ActivityState.RESUMED) {
                                 mService.updateUsageStats(r, false);
@@ -4403,7 +4431,7 @@
         }
         // If a new task is moved to the front, then mark the existing top activity as supporting
         // picture-in-picture while paused
-        if (topActivity != null) {
+        if (topActivity != null && topActivity.getStack().getStackId() != PINNED_STACK_ID) {
             topActivity.supportsPictureInPictureWhilePausing = true;
         }
 
@@ -4529,7 +4557,7 @@
             }
         }
 
-        final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
+        final TaskRecord task = mResumedActivity != null ? mResumedActivity.getTask() : null;
         if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
             if (!mService.mBooting && !mService.mBooted) {
                 // Not ready yet!
@@ -4570,7 +4598,7 @@
             return;
         }
 
-        final TaskRecord startTask = start.task;
+        final TaskRecord startTask = start.getTask();
         boolean behindFullscreen = false;
         boolean updatedConfig = false;
 
@@ -4578,7 +4606,7 @@
             final TaskRecord task = mTaskHistory.get(taskIndex);
             final ArrayList<ActivityRecord> activities = task.mActivities;
             int activityIndex =
-                    (start.task == task) ? activities.indexOf(start) : activities.size() - 1;
+                    (start.getTask() == task) ? activities.indexOf(start) : activities.size() - 1;
             for (; activityIndex >= 0; --activityIndex) {
                 final ActivityRecord r = activities.get(activityIndex);
                 updatedConfig |= r.ensureActivityConfigurationLocked(0 /* globalChanges */,
@@ -4739,7 +4767,7 @@
                                 || filterByClasses.contains(r.realActivity.getClassName())))
                         || (packageName == null && r.userId == userId);
                 if ((userId == UserHandle.USER_ALL || r.userId == userId)
-                        && (sameComponent || r.task == lastTask)
+                        && (sameComponent || r.getTask() == lastTask)
                         && (r.app == null || evenPersistent || !r.app.persistent)) {
                     if (!doit) {
                         if (r.finishing) {
@@ -4765,7 +4793,7 @@
                         }
                         r.app = null;
                     }
-                    lastTask = r.task;
+                    lastTask = r.getTask();
                     if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
                             true)) {
                         // r has been deleted from mActivities, accommodate.
@@ -4816,7 +4844,7 @@
 
                 if (DEBUG_ALL) Slog.v(
                     TAG, r.intent.getComponent().flattenToShortString()
-                    + ": task=" + r.task);
+                    + ": task=" + r.getTask());
             }
 
             RunningTaskInfo ci = new RunningTaskInfo();
@@ -4832,8 +4860,8 @@
                 topTask = false;
             }
 
-            if (top.task != null) {
-                ci.description = top.task.lastDescription;
+            if (top.getTask() != null) {
+                ci.description = top.getTask().lastDescription;
             }
             ci.numActivities = numActivities;
             ci.numRunning = numRunning;
@@ -4982,9 +5010,8 @@
             task.removeWindowContainer();
         }
 
-        final ActivityRecord r = mResumedActivity;
-        if (r != null && r.task == task) {
-            mResumedActivity = null;
+        for (ActivityRecord record : task.mActivities) {
+            onActivityRemovedFromStack(record);
         }
 
         final int taskNdx = mTaskHistory.indexOf(task);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f16849d..3e3fee5 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -164,6 +164,7 @@
 import android.view.InputEvent;
 import android.view.Surface;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -173,6 +174,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.StackWindowController;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
@@ -553,9 +555,9 @@
         }
     }
 
-    public ActivityStackSupervisor(ActivityManagerService service) {
+    public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
         mService = service;
-        mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
+        mHandler = new ActivityStackSupervisorHandler(looper);
         mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
         mKeyguardController = new KeyguardController(service, this);
     }
@@ -722,7 +724,7 @@
         }
 
         if (prev != null) {
-            prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+            prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
         }
 
         mHomeStack.moveHomeStackTaskToTop();
@@ -743,7 +745,7 @@
     }
 
     /**
-     * Returns a {@link TaskRecord} for the input id if available. Null otherwise.
+     * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
      * @param id Id of the task we would like returned.
      * @param matchMode The mode to match the given task id in.
      * @param stackId The stack to restore the task to (default launch stack will be used if
@@ -763,7 +765,7 @@
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 ActivityStack stack = stacks.get(stackNdx);
-                TaskRecord task = stack.taskForIdLocked(id);
+                final TaskRecord task = stack.taskForIdLocked(id);
                 if (task != null) {
                     return task;
                 }
@@ -778,11 +780,17 @@
         // Otherwise, check the recent tasks and return if we find it there and we are not restoring
         // the task from recents
         if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
-        TaskRecord task = mRecentTasks.taskForIdLocked(id);
-        if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
-            if (DEBUG_RECENTS && task == null) {
+        final TaskRecord task = mRecentTasks.taskForIdLocked(id);
+
+        if (task == null) {
+            if (DEBUG_RECENTS) {
                 Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
             }
+
+            return null;
+        }
+
+        if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
             return task;
         }
 
@@ -1314,7 +1322,7 @@
         mService.updateLruProcessLocked(app, true, null);
         mService.updateOomAdjLocked();
 
-        final TaskRecord task = r.task;
+        final TaskRecord task = r.getTask();
         if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                 task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
             setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
@@ -2622,7 +2630,7 @@
                 }
 
                 for (int k = 0; k < proc.activities.size(); k++) {
-                    TaskRecord otherTask = proc.activities.get(k).task;
+                    TaskRecord otherTask = proc.activities.get(k).getTask();
                     if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
                         // Don't kill process(es) that has an activity in a different task that is
                         // also in recents.
@@ -2837,7 +2845,7 @@
         final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
 
         try {
-            final TaskRecord task = r.task;
+            final TaskRecord task = r.getTask();
 
             if (r == task.getStack().getVisibleBehindActivity()) {
                 // An activity can't be pinned and visible behind at the same time. Go ahead and
@@ -2910,7 +2918,7 @@
             return false;
         }
 
-        final TaskRecord task = r.task;
+        final TaskRecord task = r.getTask();
         final ActivityStack stack = r.getStack();
         if (stack == null) {
             Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
@@ -3203,7 +3211,7 @@
 
     // Called when WindowManager has finished animating the launchingBehind activity to the back.
     private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
-        final TaskRecord task = r.task;
+        final TaskRecord task = r.getTask();
         final ActivityStack stack = task.getStack();
 
         r.mLaunchTaskBehind = false;
@@ -3216,7 +3224,7 @@
         // task has been shown briefly
         final ActivityRecord top = stack.topActivity();
         if (top != null) {
-            top.task.touchActiveTime();
+            top.getTask().touchActiveTime();
         }
     }
 
@@ -3315,17 +3323,19 @@
                 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Not releasing in-use activity: " + r);
                 continue;
             }
-            if (r.task != null) {
-                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + r.task
+
+            final TaskRecord task = r.getTask();
+            if (task != null) {
+                if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
                         + " from " + r);
                 if (firstTask == null) {
-                    firstTask = r.task;
-                } else if (firstTask != r.task) {
+                    firstTask = task;
+                } else if (firstTask != task) {
                     if (tasks == null) {
                         tasks = new ArraySet<>();
                         tasks.add(firstTask);
                     }
-                    tasks.add(r.task);
+                    tasks.add(task);
                 }
             }
         }
@@ -3664,8 +3674,8 @@
                 pw.println(header2);
                 header2 = null;
             }
-            if (lastTask != r.task) {
-                lastTask = r.task;
+            if (lastTask != r.getTask()) {
+                lastTask = r.getTask();
                 pw.print(prefix);
                 pw.print(full ? "* " : "  ");
                 pw.println(lastTask);
@@ -4080,7 +4090,7 @@
             }
         }
         final ActivityRecord r = topRunningActivityLocked();
-        final TaskRecord task = r != null ? r.task : null;
+        final TaskRecord task = r != null ? r.getTask() : null;
         if (mLockTaskModeTasks.isEmpty() && task != null
                 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
             // This task must have just been authorized.
@@ -4390,19 +4400,24 @@
             synchronized (mService) {
                 mStackId = stackId;
                 mActivityDisplay = activityDisplay;
-                switch (mStackId) {
-                    case PINNED_STACK_ID:
-                        new PinnedActivityStack(this, mRecentTasks, onTop);
-                        break;
-                    default:
-                        new ActivityStack(this, mRecentTasks, onTop);
-                        break;
-                }
                 mIdString = "ActivtyContainer{" + mStackId + "}";
+
+                createStack(stackId, onTop);
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
             }
         }
 
+        protected void createStack(int stackId, boolean onTop) {
+            switch (stackId) {
+                case PINNED_STACK_ID:
+                    new PinnedActivityStack(this, mRecentTasks, onTop);
+                    break;
+                default:
+                    new ActivityStack(this, mRecentTasks, onTop);
+                    break;
+            }
+        }
+
         /**
          * Adds the stack to specified display. Also calls WindowManager to do the same from
          * {@link ActivityStack#reparent(ActivityDisplay, boolean)}.
@@ -4926,7 +4941,7 @@
 
             mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
                     ActivityManager.START_TASK_TO_FRONT,
-                    sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
+                    sourceRecord != null ? sourceRecord.getTask().getStackId() : INVALID_STACK_ID,
                     sourceRecord, task.getStack());
             return ActivityManager.START_TASK_TO_FRONT;
         }
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 547161a..cafc4f0 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -188,10 +188,10 @@
         }
 
         ActivityRecord homeActivityRecord = mSupervisor.getHomeActivity();
-        if (homeActivityRecord != null && homeActivityRecord.task != null) {
+        if (homeActivityRecord != null && homeActivityRecord.getTask() != null) {
             // Showing credential confirmation activity in home task to avoid stopping multi-windowed
             // mode after showing the full-screen credential confirmation activity.
-            mActivityOptions.setLaunchTaskId(homeActivityRecord.task.taskId);
+            mActivityOptions.setLaunchTaskId(homeActivityRecord.getTask().taskId);
         }
 
         final UserInfo parent = mUserManager.getProfileParent(mUserId);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 18e74080..b408569 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -79,7 +79,6 @@
 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
 import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
@@ -87,8 +86,6 @@
 import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
 
-import static java.lang.Integer.MAX_VALUE;
-
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -335,7 +332,7 @@
         }
 
         if (err == ActivityManager.START_SUCCESS && sourceRecord != null
-                && sourceRecord.task.voiceSession != null) {
+                && sourceRecord.getTask().voiceSession != null) {
             // If this activity is being launched as part of a voice session, we need
             // to ensure that it is safe to do so.  If the upcoming activity will also
             // be part of the voice session, we can only launch it if it has explicitly
@@ -575,7 +572,7 @@
         // visibility instead of using this flag.
         final boolean noDisplayActivityOverHome = sourceRecord != null
                 && sourceRecord.noDisplay
-                && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
+                && sourceRecord.getTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
         if (startedActivityStackId == DOCKED_STACK_ID
                 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
             final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
@@ -625,7 +622,7 @@
                 FLAG_ACTIVITY_TASK_ON_HOME);
         ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
                         : ActivityOptions.makeBasic());
-        options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
+        options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
         mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
     }
 
@@ -763,7 +760,7 @@
                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
                                     hist.packageName);
                             newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
-                                    hist.task.taskId);
+                                    hist.getTask().taskId);
                         }
                         newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
                                 aInfo.packageName);
@@ -967,8 +964,8 @@
             // If we are not able to proceed, disassociate the activity from the task. Leaving an
             // activity in an incomplete state can lead to issues, such as performing operations
             // without a window container.
-            if (result != START_SUCCESS && mStartActivity.task != null) {
-                mStartActivity.task.removeActivity(mStartActivity);
+            if (result != START_SUCCESS && mStartActivity.getTask() != null) {
+                mStartActivity.getTask().removeActivity(mStartActivity);
             }
             mService.mWindowManager.continueSurfaceLayout();
         }
@@ -1002,7 +999,7 @@
             // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
             // still needs to be a lock task mode violation since the task gets cleared out and
             // the device would otherwise leave the locked task.
-            if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
+            if (mSupervisor.isLockTaskModeViolation(mReusedActivity.getTask(),
                     (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                             == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                 mSupervisor.showLockTaskToast();
@@ -1010,13 +1007,13 @@
                 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
 
-            if (mStartActivity.task == null) {
-                mStartActivity.task = mReusedActivity.task;
+            if (mStartActivity.getTask() == null) {
+                mStartActivity.setTask(mReusedActivity.getTask());
             }
-            if (mReusedActivity.task.intent == null) {
+            if (mReusedActivity.getTask().intent == null) {
                 // This task was started because of movement of the activity based on affinity...
                 // Now that we are actually launching it, we can assign the base intent.
-                mReusedActivity.task.setIntent(mStartActivity);
+                mReusedActivity.getTask().setIntent(mStartActivity);
             }
 
             // This code path leads to delivering a new intent, we want to make sure we schedule it
@@ -1025,7 +1022,7 @@
             if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                     || isDocumentLaunchesIntoExisting(mLaunchFlags)
                     || mLaunchSingleInstance || mLaunchSingleTask) {
-                final TaskRecord task = mReusedActivity.task;
+                final TaskRecord task = mReusedActivity.getTask();
 
                 // In this situation we want to remove all activities from the task up to the one
                 // being started. In most cases this means we are resetting the task to its initial
@@ -1037,17 +1034,17 @@
                 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
                 // task reference is needed in the call below to
                 // {@link setTargetStackAndMoveToFrontIfNeeded}.
-                if (mReusedActivity.task == null) {
-                    mReusedActivity.task = task;
+                if (mReusedActivity.getTask() == null) {
+                    mReusedActivity.setTask(task);
                 }
 
                 if (top != null) {
                     if (top.frontOfTask) {
                         // Activity aliases may mean we use different intents for the top activity,
                         // so make sure the task now has the identity of the new intent.
-                        top.task.setIntent(mStartActivity);
+                        top.getTask().setIntent(mStartActivity);
                     }
-                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                     top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                             mStartActivity.launchedFromPackage);
                 }
@@ -1098,7 +1095,7 @@
                 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                 || mLaunchSingleTop || mLaunchSingleTask);
         if (dontStart) {
-            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
+            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
             // For paranoia, make sure we have correctly resumed the top activity.
             topStack.mLastPausedActivity = null;
             if (mDoResume) {
@@ -1116,14 +1113,14 @@
             // Don't use mStartActivity.task to show the toast. We're not starting a new activity
             // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
             mSupervisor.handleNonResizableTaskIfNeeded(
-                    top.task, preferredLaunchStackId, topStack.mStackId);
+                    top.getTask(), preferredLaunchStackId, topStack.mStackId);
 
             return START_DELIVERED_TO_TOP;
         }
 
         boolean newTask = false;
         final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
-                ? mSourceRecord.task : null;
+                ? mSourceRecord.getTask() : null;
 
         // Should this be considered a new task?
         int result = START_SUCCESS;
@@ -1150,14 +1147,15 @@
         mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
                 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
         if (mSourceRecord != null) {
-            mStartActivity.task.setTaskToReturnTo(mSourceRecord);
+            mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
         }
         if (newTask) {
             EventLog.writeEvent(
-                    EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
+                    EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
+                    mStartActivity.getTask().taskId);
         }
         ActivityStack.logStartActivity(
-                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
+                EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
         mTargetStack.mLastPausedActivity = null;
 
         sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
@@ -1165,7 +1163,8 @@
         mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                 mOptions);
         if (mDoResume) {
-            final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
+            final ActivityRecord topTaskActivity =
+                    mStartActivity.getTask().topRunningActivityLocked();
             if (!mTargetStack.isFocusable()
                     || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                     && mStartActivity != topTaskActivity)) {
@@ -1197,7 +1196,7 @@
         mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
 
         mSupervisor.handleNonResizableTaskIfNeeded(
-                mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
+                mStartActivity.getTask(), preferredLaunchStackId, mTargetStack.mStackId);
 
         return START_SUCCESS;
     }
@@ -1424,7 +1423,7 @@
                     + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
             mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
             mNewTaskInfo = mSourceRecord.info;
-            mNewTaskIntent = mSourceRecord.task.intent;
+            mNewTaskIntent = mSourceRecord.getTask().intent;
         }
         mSourceRecord = null;
         mSourceStack = null;
@@ -1516,15 +1515,16 @@
         ActivityRecord curTop = (focusStack == null)
                 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
 
-        if (curTop != null
-                && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
+        final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
+        if (topTask != null
+                && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
                 && !mAvoidMoveToFront) {
             mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
             if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
-                    mSourceStack.topActivity().task == mSourceRecord.task)) {
+                    mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
                 // We really do want to push this one into the user's face, right now.
                 if (mLaunchTaskBehind && mSourceRecord != null) {
-                    intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
+                    intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
                 }
                 mMovedOtherTask = true;
 
@@ -1539,13 +1539,13 @@
                             == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
                 if (!willClearTask) {
                     final ActivityStack launchStack = getLaunchStack(
-                            mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
+                            mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
+                    final TaskRecord intentTask = intentActivity.getTask();
                     if (launchStack == null || launchStack == mTargetStack) {
                         // We only want to move to the front, if we aren't going to launch on a
                         // different stack. If we launch on a different stack, we will put the
                         // task on top there.
-                        mTargetStack.moveTaskToFrontLocked(
-                                intentActivity.task, mNoAnimation, mOptions,
+                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
                                 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                         mMovedToFront = true;
                     } else if (launchStack.mStackId == DOCKED_STACK_ID
@@ -1553,7 +1553,7 @@
                         if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                             // If we want to launch adjacent and mTargetStack is not the computed
                             // launch stack - move task to top of computed stack.
-                            intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+                            intentTask.reparent(launchStack.mStackId, ON_TOP,
                                     REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                     "launchToSide");
                         } else {
@@ -1561,8 +1561,8 @@
                             // We choose to move task to front instead of launching it adjacent
                             // when specific stack was requested explicitly and it appeared to be
                             // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
-                            mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
-                                    mOptions, mStartActivity.appTimeTracker,
+                            mTargetStack.moveTaskToFrontLocked(intentTask,
+                                    mNoAnimation, mOptions, mStartActivity.appTimeTracker,
                                     "bringToFrontInsteadOfAdjacentLaunch");
                         }
                         mMovedToFront = true;
@@ -1570,7 +1570,7 @@
                         // Target and computed stacks are on different displays and we've
                         // found a matching task - move the existing instance to that display and
                         // move it to front.
-                        intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
+                        intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
                                 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                 "reparentToDisplay");
                         mMovedToFront = true;
@@ -1582,7 +1582,7 @@
                     intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
                             true /* taskSwitch */);
                 }
-                updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
+                updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
             }
         }
         if (!mMovedToFront && mDoResume) {
@@ -1591,7 +1591,7 @@
             mTargetStack.moveToFront("intentActivityFound");
         }
 
-        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
+        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
                 mTargetStack.mStackId);
 
         // If the caller has requested that the target task be reset, then do so.
@@ -1635,7 +1635,7 @@
             // launching another activity.
             // TODO(b/36119896):  We shouldn't trigger activity launches in this path since we are
             // already launching one.
-            final TaskRecord task = intentActivity.task;
+            final TaskRecord task = intentActivity.getTask();
             task.performClearTaskLocked();
             mReuseTask = task;
             mReuseTask.setIntent(mStartActivity);
@@ -1646,7 +1646,7 @@
             mMovedOtherTask = true;
         } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                 || mLaunchSingleInstance || mLaunchSingleTask) {
-            ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
+            ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
                     mLaunchFlags);
             if (top == null) {
                 // A special case: we need to start the activity because it is not currently
@@ -1655,11 +1655,11 @@
                 mAddingToTask = true;
 
                 // We are no longer placing the activity in the task we previously thought we were.
-                mStartActivity.task = null;
+                mStartActivity.setTask(null);
                 // Now pretend like this activity is being started by the top of its task, so it
                 // is put in the right place.
                 mSourceRecord = intentActivity;
-                final TaskRecord task = mSourceRecord.task;
+                final TaskRecord task = mSourceRecord.getTask();
                 if (task != null && task.getStack() == null) {
                     // Target stack got cleared when we all activities were removed above.
                     // Go ahead and reset it.
@@ -1669,7 +1669,7 @@
                             !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
                 }
             }
-        } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
+        } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
             // In this case the top activity on the task is the same as the one being launched,
             // so we take that as a request to bring the task to the foreground. If the top
             // activity in the task is the root activity, deliver this new intent to it if it
@@ -1677,13 +1677,13 @@
             if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
                     && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
                 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
-                        intentActivity.task);
+                        intentActivity.getTask());
                 if (intentActivity.frontOfTask) {
-                    intentActivity.task.setIntent(mStartActivity);
+                    intentActivity.getTask().setIntent(mStartActivity);
                 }
                 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                         mStartActivity.launchedFromPackage);
-            } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
+            } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
                 // In this case we are launching the root activity of the task, but with a
                 // different intent. We should start a new instance on top.
                 mAddingToTask = true;
@@ -1696,13 +1696,13 @@
             // current task.
             mAddingToTask = true;
             mSourceRecord = intentActivity;
-        } else if (!intentActivity.task.rootWasReset) {
+        } else if (!intentActivity.getTask().rootWasReset) {
             // In this case we are launching into an existing task that has not yet been started
             // from its front door. The current task has been brought to the front. Ideally,
             // we'd probably like to place this new task at the bottom of its stack, but that's
             // a little hard to do with the current organization of the code so for now we'll
             // just drop it.
-            intentActivity.task.setIntent(mStartActivity);
+            intentActivity.getTask().setIntent(mStartActivity);
         }
     }
 
@@ -1736,11 +1736,11 @@
                     mService.resizeStack(
                             stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
                 } else {
-                    mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
+                    mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
                 }
             }
             if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
-                    + " in new task " + mStartActivity.task);
+                    + " in new task " + mStartActivity.getTask());
         } else {
             addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
         }
@@ -1749,7 +1749,7 @@
             mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
         }
 
-        if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
+        if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
             Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
             return START_RETURN_LOCK_TASK_MODE_VIOLATION;
         }
@@ -1758,7 +1758,7 @@
             // If stack id is specified in activity options, usually it means that activity is
             // launched not from currently focused stack (e.g. from SysUI or from shell) - in
             // that case we check the target stack.
-            updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
+            updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
                     preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
         }
         if (mDoResume) {
@@ -1768,19 +1768,19 @@
     }
 
     private int setTaskFromSourceRecord() {
-        if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
+        if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
             Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
             return START_RETURN_LOCK_TASK_MODE_VIOLATION;
         }
 
-        final TaskRecord sourceTask = mSourceRecord.task;
+        final TaskRecord sourceTask = mSourceRecord.getTask();
         final ActivityStack sourceStack = mSourceRecord.getStack();
         // We only want to allow changing stack if the target task is not the top one,
         // otherwise we would move the launching task to the other side, rather than show
         // two side by side.
         final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
         if (moveStackAllowed) {
-            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
+            mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
                     mOptions);
         }
 
@@ -1805,7 +1805,7 @@
             ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
             mKeepCurTransition = true;
             if (top != null) {
-                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+                ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
                 // For paranoia, make sure we have correctly resumed the top activity.
                 mTargetStack.mLastPausedActivity = null;
@@ -1821,7 +1821,7 @@
             // stack if so.
             final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
             if (top != null) {
-                final TaskRecord task = top.task;
+                final TaskRecord task = top.getTask();
                 task.moveActivityToFrontLocked(top);
                 top.updateOptionsLocked(mOptions);
                 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
@@ -1838,7 +1838,7 @@
         // the same task as the one that is starting it.
         addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
         if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
-                + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
+                + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
         return START_SUCCESS;
     }
 
@@ -1861,7 +1861,7 @@
                     || mLaunchSingleTop || mLaunchSingleTask) {
                 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
                         mStartActivity.appTimeTracker, "inTaskToFront");
-                ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
+                ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
                 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                     // We don't need to start a new activity, and the client said not to do
                     // anything if that is the case, so this is it!
@@ -1901,7 +1901,7 @@
 
         addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
         if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
-                + " in explicit task " + mStartActivity.task);
+                + " in explicit task " + mStartActivity.getTask());
 
         return START_SUCCESS;
     }
@@ -1913,17 +1913,17 @@
             mTargetStack.moveToFront("addingToTopTask");
         }
         final ActivityRecord prev = mTargetStack.topActivity();
-        final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
+        final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
                 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
                 mIntent, null, null, true, mStartActivity.mActivityType);
         addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
         mTargetStack.positionChildWindowContainerAtTop(task);
         if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
-                + " in new guessed " + mStartActivity.task);
+                + " in new guessed " + mStartActivity.getTask());
     }
 
     private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
-        if (mStartActivity.task == null || mStartActivity.task == parent) {
+        if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
             parent.addActivityToTop(mStartActivity);
         } else {
             mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
@@ -1973,7 +1973,7 @@
 
     private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
             int launchFlags, ActivityOptions aOptions) {
-        final TaskRecord task = r.task;
+        final TaskRecord task = r.getTask();
         ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
         if (stack != null) {
             return stack;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 21c131c..ba72dcf 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -98,6 +98,7 @@
 
 
     AppErrors(Context context, ActivityManagerService service) {
+        context.assertRuntimeOverlayThemable();
         mService = service;
         mContext = context;
     }
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 5f7f67a..347a357 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -34,6 +34,7 @@
 
     public BaseErrorDialog(Context context) {
         super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+        context.assertRuntimeOverlayThemable();
 
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 27a2461..c7f20b9f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -660,17 +660,6 @@
             // we are coming from in WM before we reparent because it became empty.
             mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
 
-            // Reset the resumed activity on the previous stack
-            if (wasResumed) {
-                sourceStack.mResumedActivity = null;
-            }
-
-            // Reset the paused activity on the previous stack
-            if (wasPaused) {
-                sourceStack.mPausingActivity = null;
-                sourceStack.removeTimeoutsForActivityLocked(r);
-            }
-
             // Move the task
             sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
             toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
@@ -1212,14 +1201,13 @@
      * be in the current task or unparented to any task.
      */
     void addActivityAtIndex(int index, ActivityRecord r) {
-        if (r.task != null && r.task != this) {
+        TaskRecord task = r.getTask();
+        if (task != null && task != this) {
             throw new IllegalArgumentException("Can not add r=" + " to task=" + this
-                    + " current parent=" + r.task);
+                    + " current parent=" + task);
         }
-        // TODO(b/36505427): Maybe make task private to ActivityRecord so we can also do
-        // onParentChanged() within the setter?
-        r.task = this;
-        r.onParentChanged();
+
+        r.setTask(this);
 
         // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
         if (!mActivities.remove(r) && r.fullscreen) {
@@ -1274,15 +1262,21 @@
     }
 
     /**
-     * @return true if this was the last activity in the task
+     * Removes the specified activity from this task.
+     * @param r The {@link ActivityRecord} to remove.
+     * @return true if this was the last activity in the task.
      */
     boolean removeActivity(ActivityRecord r) {
-        if (r.task != this) {
+        return removeActivity(r, false /*reparenting*/);
+    }
+
+    boolean removeActivity(ActivityRecord r, boolean reparenting) {
+        if (r.getTask() != this) {
             throw new IllegalArgumentException(
                     "Activity=" + r + " does not belong to task=" + this);
         }
 
-        r.task = null;
+        r.setTask(null /*task*/, reparenting);
 
         if (mActivities.remove(r) && r.fullscreen) {
             // Was previously in list.
@@ -1437,7 +1431,7 @@
     TaskThumbnail getTaskThumbnailLocked() {
         if (mStack != null) {
             final ActivityRecord resumedActivity = mStack.mResumedActivity;
-            if (resumedActivity != null && resumedActivity.task == this) {
+            if (resumedActivity != null && resumedActivity.getTask() == this) {
                 final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
                 setLastThumbnailLocked(thumbnail);
             }
@@ -1619,6 +1613,9 @@
             String iconFilename = null;
             int colorPrimary = 0;
             int colorBackground = 0;
+            int statusBarColor = 0;
+            int navigationBarColor = 0;
+            boolean topActivity = true;
             for (--activityNdx; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = mActivities.get(activityNdx);
                 if (r.taskDescription != null) {
@@ -1631,13 +1628,16 @@
                     if (colorPrimary == 0) {
                         colorPrimary = r.taskDescription.getPrimaryColor();
                     }
-                    if (colorBackground == 0) {
+                    if (topActivity) {
                         colorBackground = r.taskDescription.getBackgroundColor();
+                        statusBarColor = r.taskDescription.getStatusBarColor();
+                        navigationBarColor = r.taskDescription.getNavigationBarColor();
                     }
                 }
+                topActivity = false;
             }
             lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
-                    colorBackground);
+                    colorBackground, statusBarColor, navigationBarColor);
             if (mWindowContainerController != null) {
                 mWindowContainerController.setTaskDescription(lastTaskDescription);
             }
@@ -1953,7 +1953,7 @@
         task.updateOverrideConfiguration(bounds);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
-            activities.get(activityNdx).task = task;
+            activities.get(activityNdx).setTask(task);
         }
 
         if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 70e56b0..c11f531 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -55,6 +55,7 @@
 import android.hardware.usb.UsbManager;
 import android.media.AudioAttributes;
 import android.media.AudioDevicePort;
+import android.media.AudioFocusInfo;
 import android.media.AudioSystem;
 import android.media.AudioFormat;
 import android.media.AudioManager;
@@ -5634,8 +5635,9 @@
                 clientId, callingPackageName, flags);
     }
 
-    public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) {
-        return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa);
+    public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
+            String callingPackageName) {
+        return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
     }
 
     public void unregisterAudioFocusClient(String clientId) {
@@ -5650,6 +5652,7 @@
         return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
     }
 
+    //==========================================================================================
     private boolean readCameraSoundForced() {
         return SystemProperties.getBoolean("audio.camerasound.force", false) ||
                 mContext.getResources().getBoolean(
@@ -6430,7 +6433,7 @@
     // Audio policy management
     //==========================================================================================
     public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
-            boolean hasFocusListener) {
+            boolean hasFocusListener, boolean isFocusPolicy) {
         AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
 
         if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
@@ -6452,7 +6455,8 @@
                     Slog.e(TAG, "Cannot re-register policy");
                     return null;
                 }
-                AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener);
+                AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
+                        isFocusPolicy);
                 pcb.asBinder().linkToDeath(app, 0/*flags*/);
                 regId = app.getRegistrationId();
                 mAudioPolicies.put(pcb.asBinder(), app);
@@ -6650,15 +6654,21 @@
          * is handling ducking for audio focus.
          */
         int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
+        boolean mIsFocusPolicy = false;
 
         AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
-                boolean hasFocusListener) {
+                boolean hasFocusListener, boolean isFocusPolicy) {
             super(config);
             setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
             mPolicyCallback = token;
             mHasFocusListener = hasFocusListener;
             if (mHasFocusListener) {
                 mMediaFocusControl.addFocusFollower(mPolicyCallback);
+                // can only ever be true if there is a focus listener
+                if (isFocusPolicy) {
+                    mIsFocusPolicy = true;
+                    mMediaFocusControl.setFocusPolicy(mPolicyCallback);
+                }
             }
             connectMixes();
         }
@@ -6676,6 +6686,9 @@
         }
 
         void release() {
+            if (mIsFocusPolicy) {
+                mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
+            }
             if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
                 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
             }
@@ -6690,6 +6703,22 @@
         }
     };
 
+    //======================
+    // Audio policy: focus
+    //======================
+    /**  */
+    public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
+        synchronized (mAudioPolicies) {
+            if (!mAudioPolicies.containsKey(pcb.asBinder())) {
+                throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
+            }
+            return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
+        }
+    }
+
+    //======================
+    // misc
+    //======================
     private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
             new HashMap<IBinder, AudioPolicyProxy>();
     private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 5275c05..bcaa295 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -33,7 +33,7 @@
  * @hide
  * Class to handle all the information about a user of audio focus. The lifecycle of each
  * instance is managed by android.media.MediaFocusControl, from its addition to the audio focus
- * stack to its release.
+ * stack, or the map of focus owners for an external focus policy, to its release.
  */
 public class FocusRequester {
 
@@ -101,6 +101,21 @@
         mFocusController = ctlr;
     }
 
+    FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl,
+             IBinder source, AudioFocusDeathHandler hdlr, @NonNull MediaFocusControl ctlr) {
+        mAttributes = afi.getAttributes();
+        mClientId = afi.getClientId();
+        mPackageName = afi.getPackageName();
+        mCallingUid = afi.getClientUid();
+        mFocusGainRequest = afi.getGainRequest();
+        mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
+        mGrantFlags = afi.getFlags();
+
+        mFocusDispatcher = afl;
+        mSourceRef = source;
+        mDeathHandler = hdlr;
+        mFocusController = ctlr;
+    }
 
     boolean hasSameClient(String otherClient) {
         try {
@@ -118,6 +133,10 @@
         return (mSourceRef != null) && mSourceRef.equals(ib);
     }
 
+    boolean hasSameDispatcher(IAudioFocusDispatcher fd) {
+        return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
+    }
+
     boolean hasSamePackage(String pack) {
         try {
             return mPackageName.compareTo(pack) == 0;
@@ -369,6 +388,35 @@
         }
     }
 
+    int dispatchFocusChange(int focusChange) {
+        if (mFocusDispatcher == null) {
+            if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: no focus dispatcher"); }
+            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+        }
+        if (focusChange == AudioManager.AUDIOFOCUS_NONE) {
+            if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: AUDIOFOCUS_NONE"); }
+            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+        } else if ((focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
+                || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
+                || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
+                || focusChange == AudioManager.AUDIOFOCUS_GAIN)
+                && (mFocusGainRequest != focusChange)){
+            Log.w(TAG, "focus gain was requested with " + mFocusGainRequest
+                    + ", dispatching " + focusChange);
+        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
+                || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
+                || focusChange == AudioManager.AUDIOFOCUS_LOSS) {
+            mFocusLossReceived = focusChange;
+        }
+        try {
+            mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId);
+        } catch (android.os.RemoteException e) {
+            Log.v(TAG, "dispatchFocusChange: error talking to focus listener", e);
+            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+        }
+        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+    }
+
     AudioFocusInfo toAudioFocusInfo() {
         return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName,
                 mFocusGainRequest, mFocusLossReceived, mGrantFlags);
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index b3f1548..821e78a 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.audio;
 
+import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -23,6 +24,7 @@
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.media.IAudioFocusDispatcher;
+import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.IAudioPolicyCallback;
 import android.os.Binder;
 import android.os.IBinder;
@@ -32,7 +34,10 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
 import java.util.Stack;
 import java.text.DateFormat;
 
@@ -43,6 +48,7 @@
 public class MediaFocusControl implements PlayerFocusEnforcer {
 
     private static final String TAG = "MediaFocusControl";
+    static final boolean DEBUG = false;
 
     /**
      * set to true so the framework enforces ducking itself, without communicating to apps
@@ -155,6 +161,13 @@
             while(stackIterator.hasNext()) {
                 stackIterator.next().dump(pw);
             }
+            pw.println("\n");
+            if (mFocusPolicy == null) {
+                pw.println("No external focus policy\n");
+            } else {
+                pw.println("External focus policy: "+ mFocusPolicy + ", focus owners:\n");
+                dumpExtFocusPolicyFocusOwners(pw);
+            }
         }
         pw.println("\n");
         pw.println(" Notify on duck:  " + mNotifyFocusOwnerOnDuck + "\n");
@@ -234,6 +247,31 @@
     }
 
     /**
+     * Helper function for external focus policy:
+     * Called synchronized on mAudioFocusLock
+     * Remove focus listeners from the list of potential focus owners for a particular client when
+     * it has died.
+     */
+    private void removeFocusEntryForExtPolicy(IBinder cb) {
+        if (mFocusOwnersForFocusPolicy.isEmpty()) {
+            return;
+        }
+        boolean released = false;
+        final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
+        final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
+        while (ownerIterator.hasNext()) {
+            final Entry<String, FocusRequester> owner = ownerIterator.next();
+            final FocusRequester fr = owner.getValue();
+            if (fr.hasSameBinder(cb)) {
+                ownerIterator.remove();
+                fr.release();
+                notifyExtFocusPolicyFocusAbandon_syncAf(fr.toAudioFocusInfo());
+                break;
+            }
+        }
+    }
+
+    /**
      * Helper function:
      * Returns true if the system is in a state where the focus can be reevaluated, false otherwise.
      * The implementation guarantees that a state where focus cannot be immediately reassigned
@@ -297,7 +335,11 @@
 
         public void binderDied() {
             synchronized(mAudioFocusLock) {
-                removeFocusStackEntryOnDeath(mCb);
+                if (mFocusPolicy != null) {
+                    removeFocusEntryForExtPolicy(mCb);
+                } else {
+                    removeFocusStackEntryOnDeath(mCb);
+                }
             }
         }
     }
@@ -353,6 +395,34 @@
         }
     }
 
+    private IAudioPolicyCallback mFocusPolicy = null;
+
+    // Since we don't have a stack of focus owners when using an external focus policy, we keep
+    // track of all the focus requesters in this map, with their clientId as the key. This is
+    // used both for focus dispatch and death handling
+    private HashMap<String, FocusRequester> mFocusOwnersForFocusPolicy =
+            new HashMap<String, FocusRequester>();
+
+    void setFocusPolicy(IAudioPolicyCallback policy) {
+        if (policy == null) {
+            return;
+        }
+        synchronized (mAudioFocusLock) {
+            mFocusPolicy = policy;
+        }
+    }
+
+    void unsetFocusPolicy(IAudioPolicyCallback policy) {
+        if (policy == null) {
+            return;
+        }
+        synchronized (mAudioFocusLock) {
+            if (mFocusPolicy == policy) {
+                mFocusPolicy = null;
+            }
+        }
+    }
+
     /**
      * @param pcb non null
      */
@@ -409,6 +479,100 @@
         }
     }
 
+    /**
+     * Called synchronized on mAudioFocusLock
+     * @param afi
+     * @param requestResult
+     * @return true if the external audio focus policy (if any) is handling the focus request
+     */
+    boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi, int requestResult,
+            IAudioFocusDispatcher fd, IBinder cb) {
+        if (mFocusPolicy == null) {
+            return false;
+        }
+        if (DEBUG) {
+            Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId()
+            + " dispatcher=" + fd);
+        }
+        final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+        if (existingFr != null) {
+            if (!existingFr.hasSameDispatcher(fd)) {
+                existingFr.release();
+                final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+                mFocusOwnersForFocusPolicy.put(afi.getClientId(),
+                        new FocusRequester(afi, fd, cb, hdlr, this));
+            }
+        } else if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
+                 || requestResult == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
+            // new focus (future) focus owner to keep track of
+            final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
+            mFocusOwnersForFocusPolicy.put(afi.getClientId(),
+                    new FocusRequester(afi, fd, cb, hdlr, this));
+        }
+        try {
+            //oneway
+            mFocusPolicy.notifyAudioFocusRequest(afi, requestResult);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Can't call notifyAudioFocusRequest() on IAudioPolicyCallback "
+                    + mFocusPolicy.asBinder(), e);
+        }
+        return true;
+    }
+
+    /**
+     * Called synchronized on mAudioFocusLock
+     * @param afi
+     * @param requestResult
+     * @return true if the external audio focus policy (if any) is handling the focus request
+     */
+    boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) {
+        if (mFocusPolicy == null) {
+            return false;
+        }
+        final FocusRequester fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId());
+        if (fr != null) {
+            fr.release();
+        }
+        try {
+            //oneway
+            mFocusPolicy.notifyAudioFocusAbandon(afi);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Can't call notifyAudioFocusAbandon() on IAudioPolicyCallback "
+                    + mFocusPolicy.asBinder(), e);
+        }
+        return true;
+    }
+
+    /** see AudioManager.dispatchFocusChange(AudioFocusInfo afi, int focusChange, AudioPolicy ap) */
+    int dispatchFocusChange(AudioFocusInfo afi, int focusChange) {
+        if (DEBUG) {
+            Log.v(TAG, "dispatchFocusChange " + focusChange + " to afi client="
+                    + afi.getClientId());
+        }
+        synchronized (mAudioFocusLock) {
+            if (mFocusPolicy == null) {
+                if (DEBUG) { Log.v(TAG, "> failed: no focus policy" ); }
+                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+            }
+            final FocusRequester fr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
+            if (fr == null) {
+                if (DEBUG) { Log.v(TAG, "> failed: no such focus requester known" ); }
+                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+            }
+            return fr.dispatchFocusChange(focusChange);
+        }
+    }
+
+    private void dumpExtFocusPolicyFocusOwners(PrintWriter pw) {
+        final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
+        final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
+        while (ownerIterator.hasNext()) {
+            final Entry<String, FocusRequester> owner = ownerIterator.next();
+            final FocusRequester fr = owner.getValue();
+            fr.dump(pw);
+        }
+    }
+
     protected int getCurrentAudioFocus() {
         synchronized(mAudioFocusLock) {
             if (mFocusStack.empty()) {
@@ -487,10 +651,23 @@
                     & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
             if (enteringRingOrCall) { mRingOrCallActive = true; }
 
+            final AudioFocusInfo afiForExtPolicy;
+            if (mFocusPolicy != null) {
+                // construct AudioFocusInfo as it will be communicated to audio focus policy
+                afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(),
+                        clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/,
+                        flags);
+            } else {
+                afiForExtPolicy = null;
+            }
+
+            // handle delayed focus
             boolean focusGrantDelayed = false;
             if (!canReassignAudioFocus()) {
                 if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
-                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+                    final int result = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+                    notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, result, fd, cb);
+                    return result;
                 } else {
                     // request has AUDIOFOCUS_FLAG_DELAY_OK: focus can't be
                     // granted right now, so the requester will be inserted in the focus stack
@@ -499,6 +676,14 @@
                 }
             }
 
+            // external focus policy: delay request for focus gain?
+            final int resultWithExtPolicy = AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
+            if (notifyExtFocusPolicyFocusRequest_syncAf(
+                    afiForExtPolicy, resultWithExtPolicy, fd, cb)) {
+                // stop handling focus request here as it is handled by external audio focus policy
+                return resultWithExtPolicy;
+            }
+
             // handle the potential premature death of the new holder of the focus
             // (premature death == death before abandoning focus)
             // Register for client death notification
@@ -569,7 +754,8 @@
     /**
      * @see AudioManager#abandonAudioFocus(AudioManager.OnAudioFocusChangeListener, AudioAttributes)
      * */
-    protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa) {
+    protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa,
+            String callingPackageName) {
         // AudioAttributes are currently ignored, to be used for zones
         Log.i(TAG, " AudioFocus  abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
                 + "/" + Binder.getCallingPid()
@@ -577,6 +763,16 @@
         try {
             // this will take care of notifying the new focus owner if needed
             synchronized(mAudioFocusLock) {
+                // external focus policy?
+                if (mFocusPolicy != null) {
+                    final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(),
+                            clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/,
+                            0 /*flags*/);
+                    if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) {
+                        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+                    }
+                }
+
                 boolean exitingRingOrCall = mRingOrCallActive
                         & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
                 if (exitingRingOrCall) { mRingOrCallActive = false; }
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 82a0ff6..51aa4f8 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -103,6 +103,13 @@
         apc.init();
         synchronized(mPlayerLock) {
             mPlayers.put(newPiid, apc);
+            if (mDuckedUids.contains(new Integer(apc.getClientUid()))) {
+                if (DEBUG) { Log.v(TAG, "  > trackPlayer() piid=" + newPiid + " must be ducked"); }
+                mDuckedPlayers.add(new Integer(newPiid));
+                // FIXME here the player needs to be put in a state that is the same as if it
+                //   had been ducked as it starts. At the moment, this works already for linked
+                //   players, as is the case in gapless playback.
+            }
         }
         return newPiid;
     }
@@ -141,6 +148,13 @@
                 Log.e(TAG, "Error handling event " + event);
                 change = false;
             }
+            if (change && event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
+                    && mDuckedUids.contains(new Integer(apc.getClientUid()))) {
+                if (DEBUG) { Log.v(TAG, "  > playerEvent() piid=" + piid + " must be ducked"); }
+                if (!mDuckedPlayers.contains(new Integer(piid))) {
+                    mDuckedPlayers.add(new Integer(piid));
+                }
+            }
         }
         if (change) {
             dispatchPlaybackChange();
@@ -273,13 +287,20 @@
     // PlayerFocusEnforcer implementation
     private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();
     private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();
+    // size of 2 for typical cases of double-ducking, not expected to grow beyond that, but can
+    private final ArrayList<Integer> mDuckedUids = new ArrayList<Integer>(2);
 
     @Override
     public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
         if (DEBUG) {
             Log.v(TAG, String.format("duckPlayers: uids winner=%d loser=%d",
-                    winner.getClientUid(), loser.getClientUid())); }
+                    winner.getClientUid(), loser.getClientUid()));
+        }
         synchronized (mPlayerLock) {
+            final Integer loserUid = new Integer(loser.getClientUid());
+            if (!mDuckedUids.contains(loserUid)) {
+                mDuckedUids.add(loserUid);
+            }
             if (mPlayers.isEmpty()) {
                 return true;
             }
@@ -296,7 +317,7 @@
                         && loser.hasSameUid(apc.getClientUid())
                         && apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED)
                 {
-                    if (mDuckedPlayers.contains(piid)) {
+                    if (mDuckedPlayers.contains(new Integer(piid))) {
                         if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); }
                     } else if (apc.getAudioAttributes().getContentType() ==
                             AudioAttributes.CONTENT_TYPE_SPEECH) {
@@ -313,7 +334,7 @@
                             apc.getPlayerProxy().applyVolumeShaper(
                                     DUCK_VSHAPE,
                                     PLAY_CREATE_IF_NEEDED);
-                            mDuckedPlayers.add(piid);
+                            mDuckedPlayers.add(new Integer(piid));
                         } catch (Exception e) {
                             Log.e(TAG, "Error ducking player " + piid, e);
                             // something went wrong trying to duck, so let the app handle it
@@ -332,25 +353,36 @@
         if (DEBUG) { Log.v(TAG, "unduckPlayers: uids winner=" + winner.getClientUid()); }
         synchronized (mPlayerLock) {
             if (mDuckedPlayers.isEmpty()) {
+                mDuckedUids.remove(new Integer(winner.getClientUid()));
                 return;
             }
+            final ArrayList<Integer> playersToRemove =
+                    new ArrayList<Integer>(mDuckedPlayers.size());
             for (int piid : mDuckedPlayers) {
                 final AudioPlaybackConfiguration apc = mPlayers.get(piid);
-                if (apc != null
-                        && winner.hasSameUid(apc.getClientUid())) {
-                    try {
-                        Log.v(TAG, "unducking player" + piid);
-                        mDuckedPlayers.remove(new Integer(piid));
-                        apc.getPlayerProxy().applyVolumeShaper(
-                                DUCK_ID,
-                                VolumeShaper.Operation.REVERSE);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Error unducking player " + piid, e);
+                if (apc != null) {
+                    if (winner.hasSameUid(apc.getClientUid())) {
+                        try {
+                            Log.v(TAG, "unducking player " + piid);
+                            apc.getPlayerProxy().applyVolumeShaper(
+                                    DUCK_ID,
+                                    VolumeShaper.Operation.REVERSE);
+                        } catch (Exception e) {
+                            Log.e(TAG, "Error unducking player " + piid, e);
+                        } finally {
+                            playersToRemove.add(piid);
+                        }
                     }
                 } else {
-                    Log.e(TAG, "Error unducking player " + piid + ", player not found");
+                    // this piid was in the list of ducked players, but wasn't found, discard it
+                    Log.v(TAG, "Error unducking player " + piid + ", player not found");
+                    playersToRemove.add(piid);
                 }
             }
+            for (int piid : playersToRemove) {
+                mDuckedPlayers.remove(new Integer(piid));
+            }
+            mDuckedUids.remove(new Integer(winner.getClientUid()));
         }
     }
 
@@ -383,7 +415,7 @@
                     try {
                         Log.v(TAG, "call: muting player" + piid);
                         apc.getPlayerProxy().setVolume(0.0f);
-                        mMutedPlayers.add(piid);
+                        mMutedPlayers.add(new Integer(piid));
                     } catch (Exception e) {
                         Log.e(TAG, "call: error muting player " + piid, e);
                     }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a1a7437..ddd918f 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -339,6 +339,18 @@
         }
     }
 
+    /**
+     * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
+     */
+    private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
+        synchronized (mSyncRoot) {
+            final LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                display.getNonOverrideDisplayInfoLocked(outInfo);
+            }
+        }
+    }
+
     private void performTraversalInTransactionFromWindowManagerInternal() {
         synchronized (mSyncRoot) {
             if (!mPendingTraversal) {
@@ -1663,6 +1675,11 @@
         }
 
         @Override
+        public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
+            getNonOverrideDisplayInfoInternal(displayId, outInfo);
+        }
+
+        @Override
         public void performTraversalInTransactionFromWindowManager() {
             performTraversalInTransactionFromWindowManagerInternal();
         }
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index a947b41..addad0b 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -17,6 +17,7 @@
 package com.android.server.display;
 
 import android.graphics.Rect;
+import android.hardware.display.DisplayManagerInternal;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
@@ -62,7 +63,18 @@
 
     private final int mDisplayId;
     private final int mLayerStack;
-    private DisplayInfo mOverrideDisplayInfo; // set by the window manager
+    /**
+     * Override information set by the window manager. Will be reported instead of {@link #mInfo}
+     * if not null.
+     * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
+     * @see #getDisplayInfoLocked()
+     */
+    private DisplayInfo mOverrideDisplayInfo;
+    /**
+     * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
+     * needs to be updated.
+     * @see #getDisplayInfoLocked()
+     */
     private DisplayInfo mInfo;
 
     // The display device that this logical display is based on and which
@@ -142,6 +154,13 @@
     }
 
     /**
+     * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
+     */
+    void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) {
+        outInfo.copyFrom(mBaseDisplayInfo);
+    }
+
+    /**
      * Sets overridden logical display information from the window manager.
      * This method can be used to adjust application insets, rotation, and other
      * properties that the window manager takes care of.
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 0a6d8a4..8ad1bea 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -345,6 +345,7 @@
 
     public void notePending(JobStatus job) {
         final long now = SystemClock.uptimeMillis();
+        job.madePending = now;
         rebatchIfNeeded(now);
         mCurDataSet.incPending(job.getSourceUid(), job.getSourcePackageName(), now);
     }
@@ -357,6 +358,7 @@
 
     public void noteActive(JobStatus job) {
         final long now = SystemClock.uptimeMillis();
+        job.madeActive = now;
         rebatchIfNeeded(now);
         if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
             mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 7c231ff..cd3ba4c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -2035,27 +2035,35 @@
                     pw.print("    Evaluated priority: "); pw.println(priority);
                 }
                 pw.print("    Tag: "); pw.println(job.getTag());
+                pw.print("    Enq: ");
+                TimeUtils.formatDuration(now - job.madePending, pw);
+                pw.println(" ago");
             }
             pw.println();
             pw.println("Active jobs:");
             for (int i=0; i<mActiveServices.size(); i++) {
                 JobServiceContext jsc = mActiveServices.get(i);
                 pw.print("  Slot #"); pw.print(i); pw.print(": ");
-                if (jsc.getRunningJob() == null) {
+                final JobStatus job = jsc.getRunningJob();
+                if (job == null) {
                     pw.println("inactive");
                     continue;
                 } else {
-                    pw.println(jsc.getRunningJob().toShortString());
+                    pw.println(job.toShortString());
                     pw.print("    Running for: ");
                     TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
                     pw.print(", timeout at: ");
                     TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
                     pw.println();
-                    jsc.getRunningJob().dump(pw, "    ", false);
+                    job.dump(pw, "    ", false);
                     int priority = evaluateJobPriorityLocked(jsc.getRunningJob());
                     if (priority != JobInfo.PRIORITY_DEFAULT) {
                         pw.print("    Evaluated priority: "); pw.println(priority);
                     }
+                    pw.print("    Active at "); pw.println(job.madeActive);
+                    pw.print("    Pending for ");
+                    TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
+                    pw.println();
                 }
             }
             if (filterUid == -1) {
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index f41e187..0e04d24 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -147,7 +147,6 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-
             if (action.equals(Intent.ACTION_SCREEN_ON)
                     || action.equals(Intent.ACTION_DREAMING_STOPPED)) {
                 if (DEBUG) {
@@ -183,6 +182,11 @@
                     }
                     mIdle = true;
                     reportNewIdleState(mIdle);
+                } else {
+                    if (DEBUG) {
+                        Slog.v(TAG, "TRIGGER_IDLE received but not changing state; idle="
+                                + mIdle + " screen=" + mScreenOn);
+                    }
                 }
             }
         }
@@ -191,7 +195,7 @@
     @Override
     public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
         pw.print("Idle: ");
-        pw.println(mIdleTracker.isIdle() ? "true" : "false");
+        pw.println(mIdleTracker.isIdle());
         pw.print("Tracking ");
         pw.print(mTrackedTasks.size());
         pw.println(":");
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 47630d0..d27d0e5 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -129,6 +129,10 @@
     // Used by shell commands
     public int overrideState = 0;
 
+    // Metrics about queue latency
+    public long madePending;
+    public long madeActive;
+
     /**
      * For use only by ContentObserverController: state it is maintaining about content URIs
      * being observed.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 9e4432d..dc2ebb4 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -27,4 +27,15 @@
      * Resets all policies associated with a given user.
      */
     public abstract void resetUserState(int userId);
+
+    /**
+     * @return true if the given uid is restricted from doing networking on metered networks.
+     */
+    public abstract boolean isUidRestrictedOnMeteredNetworks(int uid);
+
+    /**
+     * @return true if networking is blocked on the given interface for the given uid according
+     * to current networking policies.
+     */
+    public abstract boolean isUidNetworkingBlocked(int uid, String ifname);
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 4e1166b..02e106e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -248,8 +248,8 @@
  */
 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     static final String TAG = "NetworkPolicy";
-    private static final boolean LOGD = false;
-    private static final boolean LOGV = false;
+    private static final boolean LOGD = true; // UNDO
+    private static final boolean LOGV = true; // UNDO
 
     private static final int VERSION_INIT = 1;
     private static final int VERSION_ADDED_SNOOZE = 2;
@@ -428,9 +428,6 @@
     @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidState = new SparseIntArray();
 
-    /** Higher priority listener before general event dispatch */
-    private INetworkPolicyListener mConnectivityListener;
-
     private final RemoteCallbackList<INetworkPolicyListener>
             mListeners = new RemoteCallbackList<>();
 
@@ -2237,15 +2234,6 @@
     }
 
     @Override
-    public void setConnectivityListener(INetworkPolicyListener listener) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-        if (mConnectivityListener != null) {
-            throw new IllegalStateException("Connectivity listener already registered");
-        }
-        mConnectivityListener = listener;
-    }
-
-    @Override
     public void registerListener(INetworkPolicyListener listener) {
         // TODO: create permission for observing network policy
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
@@ -3556,7 +3544,6 @@
                 case MSG_RULES_CHANGED: {
                     final int uid = msg.arg1;
                     final int uidRules = msg.arg2;
-                    dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3567,7 +3554,6 @@
                 }
                 case MSG_METERED_IFACES_CHANGED: {
                     final String[] meteredIfaces = (String[]) msg.obj;
-                    dispatchMeteredIfacesChanged(mConnectivityListener, meteredIfaces);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3598,7 +3584,6 @@
                 }
                 case MSG_RESTRICT_BACKGROUND_CHANGED: {
                     final boolean restrictBackground = msg.arg1 != 0;
-                    dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -3616,7 +3601,6 @@
                     final int policy = msg.arg2;
                     final Boolean notifyApp = (Boolean) msg.obj;
                     // First notify internal listeners...
-                    dispatchUidPoliciesChanged(mConnectivityListener, uid, policy);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
@@ -4049,6 +4033,74 @@
                 }
             }
         }
+
+        /**
+         * @return true if the given uid is restricted from doing networking on metered networks.
+         */
+        @Override
+        public boolean isUidRestrictedOnMeteredNetworks(int uid) {
+            final int uidRules;
+            final boolean isBackgroundRestricted;
+            synchronized (mUidRulesFirstLock) {
+                uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+                isBackgroundRestricted = mRestrictBackground;
+            }
+            return isBackgroundRestricted
+                    && !hasRule(uidRules, RULE_ALLOW_METERED)
+                    && !hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED);
+        }
+
+        /**
+         * @return true if networking is blocked on the given interface for the given uid according
+         * to current networking policies.
+         */
+        @Override
+        public boolean isUidNetworkingBlocked(int uid, String ifname) {
+            final int uidRules;
+            final boolean isBackgroundRestricted;
+            final boolean isNetworkMetered;
+            synchronized (mUidRulesFirstLock) {
+                uidRules = mUidRules.get(uid, RULE_NONE);
+                isBackgroundRestricted = mRestrictBackground;
+                synchronized (mNetworkPoliciesSecondLock) {
+                    isNetworkMetered = mMeteredIfaces.contains(ifname);
+                }
+            }
+            if (hasRule(uidRules, RULE_REJECT_ALL)) {
+                if (LOGV) logUidStatus(uid, "blocked by power restrictions");
+                return true;
+            }
+            if (!isNetworkMetered) {
+                if (LOGV) logUidStatus(uid, "allowed on unmetered network");
+                return false;
+            }
+            if (hasRule(uidRules, RULE_REJECT_METERED)) {
+                if (LOGV) logUidStatus(uid, "blacklisted on metered network");
+                return true;
+            }
+            if (hasRule(uidRules, RULE_ALLOW_METERED)) {
+                if (LOGV) logUidStatus(uid, "whitelisted on metered network");
+                return false;
+            }
+            if (hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED)) {
+                if (LOGV) logUidStatus(uid, "temporary whitelisted on metered network");
+                return false;
+            }
+            if (isBackgroundRestricted) {
+                if (LOGV) logUidStatus(uid, "blocked when background is restricted");
+                return true;
+            }
+            if (LOGV) logUidStatus(uid, "allowed by default");
+            return false;
+        }
+    }
+
+    private static boolean hasRule(int uidRules, int rule) {
+        return (uidRules & rule) != 0;
+    }
+
+    private static void logUidStatus(int uid, String descr) {
+        Slog.d(TAG, String.format("uid %d is %s", uid, descr));
     }
 
     /**
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 5bdef9e..3705946 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -325,13 +325,11 @@
             // Disable all other overlays.
             allOverlays.remove(oi);
             for (int i = 0; i < allOverlays.size(); i++) {
-                mSettings.setEnabled(allOverlays.get(i).packageName, userId, false);
+                // TODO: Optimize this to only send updates after all changes.
+                setEnabled(allOverlays.get(i).packageName, false, userId);
             }
 
-            final PackageInfo targetPackage =
-                    mPackageManager.getPackageInfo(oi.targetPackageName, userId);
-            mSettings.setEnabled(packageName, userId, enable);
-            updateState(targetPackage, overlayPackage, userId);
+            setEnabled(packageName, enable, userId);
             return true;
         } catch (OverlayManagerSettings.BadKeyException e) {
             return false;
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index b0730ef..f6e96b2 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -47,7 +48,7 @@
  * service and handling all interactions in a timely manner.
  * @hide
  */
-final class EphemeralResolverConnection {
+final class EphemeralResolverConnection implements DeathRecipient {
     // This is running in a critical section and the timeout must be sufficiently low
     private static final long BIND_SERVICE_TIMEOUT_MS =
             ("eng".equals(Build.TYPE)) ? 300 : 200;
@@ -65,7 +66,7 @@
 
     public EphemeralResolverConnection(Context context, ComponentName componentName) {
         mContext = context;
-        mIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE).setComponent(componentName);
+        mIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE).setComponent(componentName);
     }
 
     public final List<InstantAppResolveInfo> getInstantAppResolveInfoList(int hashPrefix[],
@@ -171,6 +172,15 @@
         }
     }
 
+    @Override
+    public void binderDied() {
+        if (mRemoteInstance != null) {
+            mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
+        }
+        mRemoteInstance = null;
+        mBindRequested = false;
+    }
+
     /**
      * Asynchronous callback when results come back from ephemeral resolution phase two.
      */
@@ -183,7 +193,11 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (mLock) {
-                mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
+                try {
+                    service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/);
+                    mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
+                } catch (RemoteException e) {
+                }
                 mLock.notifyAll();
             }
         }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 7eef7ad..9f7c4a2 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -66,6 +66,7 @@
     public static final int FLAG_FREE_CACHE_V2 = 1 << 13;
     public static final int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
     public static final int FLAG_FREE_CACHE_NOOP = 1 << 15;
+    public static final int FLAG_FORCE = 1 << 16;
 
     private final boolean mIsolated;
 
@@ -202,6 +203,15 @@
         }
     }
 
+    public void fixupAppData(String uuid, int flags) throws InstallerException {
+        if (!checkBeforeRemote()) return;
+        try {
+            mInstalld.fixupAppData(uuid, flags);
+        } catch (Exception e) {
+            throw InstallerException.from(e);
+        }
+    }
+
     public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
             String dataAppName, int appId, String seInfo, int targetSdkVersion)
             throws InstallerException {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 0b40fc5..f79f6f4 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -242,18 +242,8 @@
             try {
                 UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
                 if (callingUserInfo.isManagedProfile()) {
-
-                    // STOPSHIP Remove the whitelist.
-                    if ("com.google.android.talk".equals(callingPackage)
-                            || "com.google.android.quicksearchbox".equals(callingPackage)
-                            || "com.google.android.googlequicksearchbox".equals(callingPackage)
-                            ) {
-                        return false;
-                    }
-                    // STOPSHIP Change it to 'e'.
-                    Slog.wtfStack(TAG, message + " by " + callingPackage + " for another profile "
+                    Slog.w(TAG, message + " by " + callingPackage + " for another profile "
                             + targetUserId + " from " + callingUserId);
-
                     return false;
                 }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 365a8e8..d5c4fb9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -842,11 +842,11 @@
 
     /** The service connection to the ephemeral resolver */
     final EphemeralResolverConnection mInstantAppResolverConnection;
+    /** Component used to show resolver settings for Instant Apps */
+    final ComponentName mInstantAppResolverSettingsComponent;
 
     /** Component used to install ephemeral applications */
     ComponentName mInstantAppInstallerComponent;
-    /** Component used to show resolver settings for Instant Apps */
-    ComponentName mInstantAppResolverSettingsComponent;
     ActivityInfo mInstantAppInstallerActivity;
     final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo();
 
@@ -2385,6 +2385,10 @@
 
             final VersionInfo ver = mSettings.getInternalVersion();
             mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
+            if (mIsUpgrade) {
+                logCriticalInfo(Log.INFO,
+                        "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
+            }
 
             // when upgrading from pre-M, promote system app permissions from install to runtime
             mPromoteSystemApps =
@@ -2713,6 +2717,15 @@
                     UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
                     true /* onlyCoreApps */);
             mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "fixup");
+                try {
+                    mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
+                            StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+                } catch (InstallerException e) {
+                    Slog.w(TAG, "Trouble fixing GIDs", e);
+                }
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+
                 if (deferPackages == null || deferPackages.isEmpty()) {
                     return;
                 }
@@ -2803,11 +2816,13 @@
                 }
                 mInstantAppResolverConnection =
                         new EphemeralResolverConnection(mContext, ephemeralResolverComponent);
+                mInstantAppResolverSettingsComponent =
+                        getEphemeralResolverSettingsLPr(ephemeralResolverComponent);
             } else {
                 mInstantAppResolverConnection = null;
+                mInstantAppResolverSettingsComponent = null;
             }
             updateInstantAppInstallerLocked();
-            mInstantAppResolverSettingsComponent = getEphemeralResolverSettingsLPr();
 
             // Read and update the usage of dex files.
             // Do this at the end of PM init so that all the packages have their
@@ -3041,10 +3056,18 @@
                 MATCH_DIRECT_BOOT_AWARE
                 | MATCH_DIRECT_BOOT_UNAWARE
                 | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
-        final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
-        final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
+        final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE);
+        List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
                 resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
-
+        // temporarily look for the old action
+        if (resolvers.size() == 0) {
+            if (DEBUG_EPHEMERAL) {
+                Slog.d(TAG, "Ephemeral resolver not found with new action; try old one");
+            }
+            resolverIntent.setAction(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
+            resolvers = queryIntentServicesInternal(resolverIntent, null,
+                    resolveFlags, UserHandle.USER_SYSTEM, callingUid, false /*includeInstantApps*/);
+        }
         final int N = resolvers.size();
         if (N == 0) {
             if (DEBUG_EPHEMERAL) {
@@ -3083,7 +3106,7 @@
     }
 
     private @Nullable ActivityInfo getEphemeralInstallerLPr() {
-        final Intent intent = new Intent(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+        final Intent intent = new Intent(Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
@@ -3091,8 +3114,17 @@
                 MATCH_DIRECT_BOOT_AWARE
                 | MATCH_DIRECT_BOOT_UNAWARE
                 | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
-        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+        List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
                 resolveFlags, UserHandle.USER_SYSTEM);
+        // temporarily look for the old action
+        if (matches.isEmpty()) {
+            if (DEBUG_EPHEMERAL) {
+                Slog.d(TAG, "Ephemeral installer not found with new action; try old one");
+            }
+            intent.setAction(Intent.ACTION_INSTALL_EPHEMERAL_PACKAGE);
+            matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
+                    resolveFlags, UserHandle.USER_SYSTEM);
+        }
         Iterator<ResolveInfo> iter = matches.iterator();
         while (iter.hasNext()) {
             final ResolveInfo rInfo = iter.next();
@@ -3115,35 +3147,27 @@
         }
     }
 
-    private @Nullable ComponentName getEphemeralResolverSettingsLPr() {
-        final Intent intent = new Intent(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
-        intent.addCategory(Intent.CATEGORY_DEFAULT);
-        final int resolveFlags =
-                MATCH_DIRECT_BOOT_AWARE
-                | MATCH_DIRECT_BOOT_UNAWARE
-                | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0);
-        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
-                resolveFlags, UserHandle.USER_SYSTEM);
-        Iterator<ResolveInfo> iter = matches.iterator();
-        while (iter.hasNext()) {
-            final ResolveInfo rInfo = iter.next();
-            final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
-            if (ps != null) {
-                final PermissionsState permissionsState = ps.getPermissionsState();
-                if (permissionsState.hasPermission(Manifest.permission.ACCESS_INSTANT_APPS, 0)) {
-                    continue;
-                }
+    private @Nullable ComponentName getEphemeralResolverSettingsLPr(
+            @NonNull ComponentName resolver) {
+        final Intent intent =  new Intent(Intent.ACTION_INSTANT_APP_RESOLVER_SETTINGS)
+                .addCategory(Intent.CATEGORY_DEFAULT)
+                .setPackage(resolver.getPackageName());
+        final int resolveFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+        List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+                UserHandle.USER_SYSTEM);
+        // temporarily look for the old action
+        if (matches.isEmpty()) {
+            if (DEBUG_EPHEMERAL) {
+                Slog.d(TAG, "Ephemeral resolver settings not found with new action; try old one");
             }
-            iter.remove();
+            intent.setAction(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS);
+            matches = queryIntentActivitiesInternal(intent, null, resolveFlags,
+                    UserHandle.USER_SYSTEM);
         }
-        if (matches.size() == 0) {
+        if (matches.isEmpty()) {
             return null;
-        } else if (matches.size() == 1) {
-            return matches.get(0).getComponentInfo().getComponentName();
-        } else {
-            throw new RuntimeException(
-                    "There must be at most one ephemeral resolver settings; found " + matches);
         }
+        return matches.get(0).getComponentInfo().getComponentName();
     }
 
     private void primeDomainVerificationsLPw(int userId) {
@@ -16961,6 +16985,15 @@
                 return;
             }
 
+            // Shared libraries for the package need to be updated.
+            synchronized (mPackages) {
+                try {
+                    updateSharedLibrariesLPr(pkg, null);
+                } catch (PackageManagerException e) {
+                    Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
+                }
+            }
+
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
             // Do not run PackageDexOptimizer through the local performDexOpt
             // method because `pkg` may not be in `mPackages` yet.
@@ -17009,6 +17042,7 @@
                         args.user, installerPackageName, volumeUuid, res, args.installReason);
             }
         }
+
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
             if (ps != null) {
@@ -17635,6 +17669,7 @@
         int removedAppId = -1;
         int[] origUsers;
         int[] removedUsers = null;
+        int[] broadcastUsers = null;
         SparseArray<Integer> installReasons;
         boolean isRemovedPackageSystemUpdate = false;
         boolean isUpdate;
@@ -17708,16 +17743,16 @@
             extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
             if (removedPackage != null) {
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
-                        extras, 0, null, null, removedUsers);
+                        extras, 0, null, null, broadcastUsers);
                 if (dataRemoved && !isRemovedPackageSystemUpdate) {
                     sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
                             removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
-                            null, null, removedUsers);
+                            null, null, broadcastUsers);
                 }
             }
             if (removedAppId >= 0) {
                 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, 0, null, null,
-                        removedUsers);
+                        broadcastUsers);
             }
         }
     }
@@ -17746,6 +17781,20 @@
                 outInfo.removedUsers = deletedPs != null
                         ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
                         : null;
+                if (outInfo.removedUsers == null) {
+                    outInfo.broadcastUsers = null;
+                } else {
+                    outInfo.broadcastUsers = EMPTY_INT_ARRAY;
+                    int[] allUsers = outInfo.removedUsers;
+                    for (int i = allUsers.length - 1; i >= 0; --i) {
+                        final int userId = allUsers[i];
+                        if (deletedPs.getInstantApp(userId)) {
+                            continue;
+                        }
+                        outInfo.broadcastUsers =
+                                ArrayUtils.appendInt(outInfo.broadcastUsers, userId);
+                    }
+                }
             }
         }
 
@@ -20854,13 +20903,6 @@
                 mSettings.dumpRestoredPermissionGrantsLPr(pw, dumpState);
             }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) {
-                // XXX should handle packageName != null by dumping only install data that
-                // the given package is involved with.
-                if (dumpState.onTitlePrinted()) pw.println();
-                mInstallerService.dump(new IndentingPrintWriter(pw, "  ", 120));
-            }
-
             if (!checkin && dumpState.isDumping(DumpState.DUMP_FROZEN) && packageName == null) {
                 // XXX should handle packageName != null by dumping only install data that
                 // the given package is involved with.
@@ -20931,6 +20973,14 @@
                 }
             }
         }
+
+        // PackageInstaller should be called outside of mPackages lock
+        if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) {
+            // XXX should handle packageName != null by dumping only install data that
+            // the given package is involved with.
+            if (dumpState.onTitlePrinted()) pw.println();
+            mInstallerService.dump(new IndentingPrintWriter(pw, "  ", 120));
+        }
     }
 
     private void dumpProto(FileDescriptor fd) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6fb056a..554deae 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4777,7 +4777,7 @@
             pw.print(" notLaunched=");
             pw.print(ps.getNotLaunched(user.id));
             pw.print(" enabled=");
-            pw.println(ps.getEnabled(user.id));
+            pw.print(ps.getEnabled(user.id));
             pw.print(" instant=");
             pw.println(ps.getInstantApp(user.id));
             String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b507df0..95fb5af 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2945,6 +2945,7 @@
                 }
                 mStatusBar = win;
                 mStatusBarController.setWindow(win);
+                setKeyguardOccludedLw(mKeyguardOccluded, true /* force */);
                 break;
             case TYPE_NAVIGATION_BAR:
                 mContext.enforceCallingOrSelfPermission(
@@ -3832,7 +3833,7 @@
             mPendingKeyguardOccluded = occluded;
             mKeyguardOccludedChanged = true;
         } else {
-            setKeyguardOccludedLw(occluded);
+            setKeyguardOccludedLw(occluded, false /* force */);
         }
     }
 
@@ -3841,7 +3842,7 @@
             if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
                     + mPendingKeyguardOccluded);
             mKeyguardOccludedChanged = false;
-            if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
+            if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */)) {
                 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
             }
         }
@@ -5254,11 +5255,8 @@
             }
         }
 
-        // Don't allow snapshots to influence SystemUI visibility flags.
-        // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
-                && attrs.type < FIRST_SYSTEM_WINDOW
-                && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
+                && attrs.type < FIRST_SYSTEM_WINDOW;
         final int stackId = win.getStackId();
         if (mTopFullscreenOpaqueWindowState == null && visible) {
             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
@@ -5475,23 +5473,27 @@
      *
      * @return Whether the flags have changed and we have to redo the layout.
      */
-    private boolean setKeyguardOccludedLw(boolean isOccluded) {
+    private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force) {
         if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
         boolean wasOccluded = mKeyguardOccluded;
         boolean showing = mKeyguardDelegate.isShowing();
         if (wasOccluded && !isOccluded && showing) {
             mKeyguardOccluded = false;
             mKeyguardDelegate.setOccluded(false, true /* animate */);
-            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
-            if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
-                mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+            if (mStatusBar != null) {
+                mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+                if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
+                    mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+                }
             }
             return true;
         } else if (!wasOccluded && isOccluded && showing) {
             mKeyguardOccluded = true;
             mKeyguardDelegate.setOccluded(true, false /* animate */);
-            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
-            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+            if (mStatusBar != null) {
+                mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+                mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+            }
             return true;
         } else if (wasOccluded != isOccluded) {
             mKeyguardOccluded = isOccluded;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9c4e700..a60dae7 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2671,11 +2671,11 @@
             public void run() {
                 synchronized (this) {
                     if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
-                        ShutdownThread.rebootSafeMode(mContext, confirm);
+                        ShutdownThread.rebootSafeMode(getUiContext(), confirm);
                     } else if (haltMode == HALT_MODE_REBOOT) {
-                        ShutdownThread.reboot(mContext, reason, confirm);
+                        ShutdownThread.reboot(getUiContext(), reason, confirm);
                     } else {
-                        ShutdownThread.shutdown(mContext, reason, confirm);
+                        ShutdownThread.shutdown(getUiContext(), reason, confirm);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 841e2a1..864e83e 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -79,7 +79,7 @@
     private static final int SHUTDOWN_VIBRATE_MS = 500;
 
     // state tracking
-    private static Object sIsStartedGuard = new Object();
+    private static final Object sIsStartedGuard = new Object();
     private static boolean sIsStarted = false;
 
     private static boolean mReboot;
@@ -121,7 +121,8 @@
      * state etc.  Must be called from a Looper thread in which its UI
      * is shown.
      *
-     * @param context Context used to display the shutdown progress dialog.
+     * @param context Context used to display the shutdown progress dialog. This must be a context
+     *                suitable for displaying UI (aka Themable).
      * @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
      * @param confirm true if user confirmation is needed before shutting down.
      */
@@ -132,7 +133,11 @@
         shutdownInner(context, confirm);
     }
 
-    static void shutdownInner(final Context context, boolean confirm) {
+    private static void shutdownInner(final Context context, boolean confirm) {
+        // ShutdownThread is called from many places, so best to verify here that the context passed
+        // in is themed.
+        context.assertRuntimeOverlayThemable();
+
         // ensure that only one thread is trying to power down.
         // any additional calls are just returned
         synchronized (sIsStartedGuard) {
@@ -204,7 +209,8 @@
      * state etc.  Must be called from a Looper thread in which its UI
      * is shown.
      *
-     * @param context Context used to display the shutdown progress dialog.
+     * @param context Context used to display the shutdown progress dialog. This must be a context
+     *                suitable for displaying UI (aka Themable).
      * @param reason code to pass to the kernel (e.g. "recovery"), or null.
      * @param confirm true if user confirmation is needed before shutting down.
      */
@@ -220,7 +226,8 @@
      * Request a reboot into safe mode.  Must be called from a Looper thread in which its UI
      * is shown.
      *
-     * @param context Context used to display the shutdown progress dialog.
+     * @param context Context used to display the shutdown progress dialog. This must be a context
+     *                suitable for displaying UI (aka Themable).
      * @param confirm true if user confirmation is needed before shutting down.
      */
     public static void rebootSafeMode(final Context context, boolean confirm) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 212bd61..32871bb 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.statusbar;
 
+import android.app.ActivityThread;
 import android.app.StatusBarManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -61,6 +62,7 @@
     private static final boolean SPEW = false;
 
     private final Context mContext;
+
     private final WindowManagerService mWindowManager;
     private Handler mHandler = new Handler();
     private NotificationDelegate mNotificationDelegate;
@@ -761,8 +763,10 @@
         enforceStatusBarService();
         long identity = Binder.clearCallingIdentity();
         try {
+            // ShutdownThread displays UI, so give it a UI context.
             mHandler.post(() ->
-                    ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, false));
+                    ShutdownThread.shutdown(getUiContext(),
+                        PowerManager.SHUTDOWN_USER_REQUESTED, false));
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -777,10 +781,12 @@
         long identity = Binder.clearCallingIdentity();
         try {
             mHandler.post(() -> {
+                // ShutdownThread displays UI, so give it a UI context.
                 if (safeMode) {
-                    ShutdownThread.rebootSafeMode(mContext, false);
+                    ShutdownThread.rebootSafeMode(getUiContext(), false);
                 } else {
-                    ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, false);
+                    ShutdownThread.reboot(getUiContext(),
+                            PowerManager.SHUTDOWN_USER_REQUESTED, false);
                 }
             });
         } finally {
@@ -1014,4 +1020,8 @@
             }
         }
     }
+
+    private static final Context getUiContext() {
+        return ActivityThread.currentActivityThread().getSystemUiContext();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 4b4be40..2bc3c5f 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -566,7 +566,7 @@
             return false;
         }
 
-        mContainer.startingData = new SnapshotStartingData(mService, snapshot.getSnapshot());
+        mContainer.startingData = new SnapshotStartingData(mService, snapshot);
         scheduleAddStartingWindow();
         return true;
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3c68e4f..4ebf1fc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -180,11 +180,23 @@
     // Mapping from a token IBinder to a WindowToken object on this display.
     private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
 
+    // Initial display metrics.
     int mInitialDisplayWidth = 0;
     int mInitialDisplayHeight = 0;
     int mInitialDisplayDensity = 0;
+
+    /**
+     * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
+     * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
+     * @see WindowManagerService#setForcedDisplaySize(int, int, int)
+     */
     int mBaseDisplayWidth = 0;
     int mBaseDisplayHeight = 0;
+    /**
+     * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
+     * but can be set from Settings or via shell command "adb shell wm density".
+     * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
+     */
     int mBaseDisplayDensity = 0;
     boolean mDisplayScalingDisabled;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -1497,8 +1509,12 @@
     }
 
     void updateDisplayInfo() {
+        // Check if display metrics changed and update base values if needed.
+        updateBaseDisplayMetricsIfNeeded();
+
         mDisplay.getDisplayInfo(mDisplayInfo);
         mDisplay.getMetrics(mDisplayMetrics);
+
         for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
             mTaskStackContainers.get(i).updateDisplayInfo(null);
         }
@@ -1514,10 +1530,11 @@
             }
         }
 
-        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
-        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
-        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
-        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
+        updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
+                mDisplayInfo.logicalDensityDpi);
+        mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+        mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+        mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
     }
 
     void getLogicalDisplayRect(Rect out) {
@@ -1547,6 +1564,42 @@
         }
     }
 
+    /**
+     * If display metrics changed, overrides are not set and it's not just a rotation - update base
+     * values.
+     */
+    private void updateBaseDisplayMetricsIfNeeded() {
+        // Get real display metrics without overrides from WM.
+        mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
+        final int orientation = mDisplayInfo.rotation;
+        final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+        final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
+        final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
+        final int newDensity = mDisplayInfo.logicalDensityDpi;
+
+        final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth
+                || mInitialDisplayHeight != newHeight
+                || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi;
+
+        if (displayMetricsChanged) {
+            // Check if display size or density is forced.
+            final boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
+                    || mBaseDisplayHeight != mInitialDisplayHeight;
+            final boolean isDisplayDensityForced = mBaseDisplayDensity != mInitialDisplayDensity;
+
+            // If there is an override set for base values - use it, otherwise use new values.
+            updateBaseDisplayMetrics(isDisplaySizeForced ? mBaseDisplayWidth : newWidth,
+                    isDisplaySizeForced ? mBaseDisplayHeight : newHeight,
+                    isDisplayDensityForced ? mBaseDisplayDensity : newDensity);
+
+            // Real display metrics changed, so we should also update initial values.
+            mInitialDisplayWidth = newWidth;
+            mInitialDisplayHeight = newHeight;
+            mInitialDisplayDensity = newDensity;
+            mService.reconfigureDisplayLocked(this);
+        }
+    }
+
     /** Sets the maximum width the screen resolution can be */
     void setMaxUiWidth(int width) {
         if (DEBUG_DISPLAY) {
@@ -2867,7 +2920,11 @@
                     if (stack != null) {
                         stack.getBounds(frame);
                     }
-                } else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
+
+                    // We want to screenshot with the exact bounds of the surface of the app. Thus,
+                    // intersect it with the frame.
+                    frame.intersect(w.mFrame);
+                }else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
                     final Rect wf = w.mFrame;
                     final Rect cr = w.mContentInsets;
                     int left = wf.left + cr.left;
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index e73d4d25..35f35db 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import android.app.ActivityManager.TaskSnapshot;
 import android.graphics.GraphicBuffer;
 import android.view.WindowManagerPolicy.StartingSurface;
 
@@ -25,9 +26,9 @@
 class SnapshotStartingData extends StartingData {
 
     private final WindowManagerService mService;
-    private final GraphicBuffer mSnapshot;
+    private final TaskSnapshot mSnapshot;
 
-    SnapshotStartingData(WindowManagerService service, GraphicBuffer snapshot) {
+    SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot) {
         super(service);
         mService = service;
         mSnapshot = snapshot;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3ffb093..b816d81 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -17,15 +17,14 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static com.android.server.EventLogTags.WM_TASK_REMOVED;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -40,7 +39,6 @@
 import android.view.Surface;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b8d0b8c..48b01f4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -28,6 +28,7 @@
 import android.app.ActivityManager.TaskSnapshot;
 import android.graphics.Canvas;
 import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
 import android.os.Environment;
 import android.util.ArraySet;
 import android.view.WindowManagerPolicy.StartingSurface;
@@ -152,7 +153,7 @@
      * MANAGER LOCK WHEN CALLING THIS METHOD!
      */
     StartingSurface createStartingSurface(AppWindowToken token,
-            GraphicBuffer snapshot) {
+            TaskSnapshot snapshot) {
         return TaskSnapshotSurface.create(mService, token, snapshot);
     }
 
@@ -166,8 +167,17 @@
         if (buffer == null) {
             return null;
         }
+        final WindowState mainWindow = top.findMainWindow();
         return new TaskSnapshot(buffer, top.getConfiguration().orientation,
-                top.findMainWindow().mStableInsets, false /* reduced */, 1f /* scale */);
+                minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */,
+                1f /* scale */);
+    }
+
+    private Rect minRect(Rect rect1, Rect rect2) {
+        return new Rect(Math.min(rect1.left, rect2.left),
+                Math.min(rect1.top, rect2.top),
+                Math.min(rect1.right, rect2.right),
+                Math.min(rect1.bottom, rect2.bottom));
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 04403e2..1591e48 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -16,20 +16,35 @@
 
 package com.android.server.wm;
 
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.graphics.Color.WHITE;
+import static android.graphics.Color.alpha;
+import static android.view.SurfaceControl.HIDDEN;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getColorViewLeftInset;
+import static com.android.internal.policy.DecorView.getColorViewTopInset;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.app.ActivityManager.TaskDescription;
-import android.graphics.Bitmap;
+import android.app.ActivityManager.TaskSnapshot;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.GraphicBuffer;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -37,17 +52,22 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.util.MergedConfiguration;
 import android.util.Slog;
 import android.view.IWindowSession;
 import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicy.StartingSurface;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.DecorView;
 import com.android.internal.view.BaseIWindow;
 
 /**
@@ -57,19 +77,57 @@
  */
 class TaskSnapshotSurface implements StartingSurface {
 
+    private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
+
+    /**
+     * When creating the starting window, we use the exact same layout flags such that we end up
+     * with a window with the exact same dimensions etc. However, these flags are not used in layout
+     * and might cause other side effects so we exclude them.
+     */
+    private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+            | FLAG_NOT_TOUCHABLE
+            | FLAG_NOT_TOUCH_MODAL
+            | FLAG_ALT_FOCUSABLE_IM
+            | FLAG_NOT_FOCUSABLE
+            | FLAG_HARDWARE_ACCELERATED
+            | FLAG_IGNORE_CHEEK_PRESSES
+            | FLAG_LOCAL_FOCUS_MODE
+            | FLAG_SLIPPERY
+            | FLAG_WATCH_OUTSIDE_TOUCH
+            | FLAG_SPLIT_TOUCH
+            | FLAG_SCALED
+            | FLAG_SECURE;
+
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
     private static final int MSG_REPORT_DRAW = 0;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
     private final Window mWindow;
     private final Surface mSurface;
+    private SurfaceControl mChildSurfaceControl;
     private final IWindowSession mSession;
     private final WindowManagerService mService;
+    private final Rect mTaskBounds;
+    private final Rect mStableInsets = new Rect();
+    private final Rect mContentInsets = new Rect();
+    private final Rect mFrame = new Rect();
+    private final TaskSnapshot mSnapshot;
+    private final CharSequence mTitle;
     private boolean mHasDrawn;
     private boolean mReportNextDraw;
-    private Paint mFillBackgroundPaint = new Paint();
+    private long mShownTime;
+    private final Handler mHandler;
+    private final boolean mSizeMismatch;
+    private final Paint mBackgroundPaint = new Paint();
+    private final Paint mStatusBarPaint = new Paint();
+    private final Paint mNavigationBarPaint = new Paint();
+    private final int mStatusBarColor;
+    private final int mNavigationBarColor;
+    private final int mSysUiVis;
+    private final int mWindowFlags;
+    private final int mWindowPrivateFlags;
 
     static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
-            GraphicBuffer snapshot) {
+            TaskSnapshot snapshot) {
 
         final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
         final Window window = new Window();
@@ -78,32 +136,51 @@
         final Surface surface = new Surface();
         final Rect tmpRect = new Rect();
         final Rect tmpFrame = new Rect();
+        final Rect taskBounds;
+        final Rect tmpContentInsets = new Rect();
+        final Rect tmpStableInsets = new Rect();
         final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
-        int fillBackgroundColor = Color.WHITE;
+        int backgroundColor = WHITE;
+        int statusBarColor = 0;
+        int navigationBarColor = 0;
+        final int sysUiVis;
+        final int windowFlags;
+        final int windowPrivateFlags;
         synchronized (service.mWindowMap) {
+            final WindowState mainWindow = token.findMainWindow();
+            if (mainWindow == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+                        + token);
+                return null;
+            }
+            sysUiVis = mainWindow.getSystemUiVisibility();
+            windowFlags = mainWindow.getAttrs().flags;
+            windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+
             layoutParams.type = TYPE_APPLICATION_STARTING;
-            layoutParams.format = snapshot.getFormat();
-            layoutParams.flags = FLAG_LAYOUT_INSET_DECOR
-                    | FLAG_LAYOUT_IN_SCREEN
+            layoutParams.format = snapshot.getSnapshot().getFormat();
+            layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
                     | FLAG_NOT_FOCUSABLE
-                    | FLAG_NOT_TOUCHABLE
-                    | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+                    | FLAG_NOT_TOUCHABLE;
             layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
             layoutParams.token = token.token;
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
-
-            // TODO: Inherit behavior whether to draw behind status bar/nav bar.
-            layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+            layoutParams.systemUiVisibility = sysUiVis;
             final Task task = token.getTask();
             if (task != null) {
-                layoutParams.setTitle(String.format(TITLE_FORMAT,task.mTaskId));
+                layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
 
                 final TaskDescription taskDescription = task.getTaskDescription();
                 if (taskDescription != null) {
-                    fillBackgroundColor = taskDescription.getBackgroundColor();
+                    backgroundColor = taskDescription.getBackgroundColor();
+                    statusBarColor = taskDescription.getStatusBarColor();
+                    navigationBarColor = taskDescription.getNavigationBarColor();
                 }
+                taskBounds = new Rect();
+                task.getBounds(taskBounds);
+            } else {
+                taskBounds = null;
             }
         }
         try {
@@ -118,31 +195,57 @@
             // Local call.
         }
         final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
-                surface, fillBackgroundColor);
+                surface, snapshot, layoutParams.getTitle(), backgroundColor, statusBarColor,
+                navigationBarColor, sysUiVis, windowFlags, windowPrivateFlags, taskBounds);
         window.setOuter(snapshotSurface);
         try {
             session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
-                    tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpMergedConfiguration,
-                    surface);
+                    tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
+                    tmpMergedConfiguration, surface);
         } catch (RemoteException e) {
             // Local call.
         }
-        snapshotSurface.drawSnapshot(snapshot);
+        snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
+        snapshotSurface.drawSnapshot();
         return snapshotSurface;
     }
 
     @VisibleForTesting
     TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface,
-            int fillBackgroundColor) {
+            TaskSnapshot snapshot, CharSequence title, int backgroundColor, int statusBarColor,
+            int navigationBarColor, int sysUiVis, int windowFlags, int windowPrivateFlags,
+            Rect taskBounds) {
         mService = service;
+        mHandler = new Handler(mService.mH.getLooper());
         mSession = WindowManagerGlobal.getWindowSession();
         mWindow = window;
         mSurface = surface;
-        mFillBackgroundPaint.setColor(fillBackgroundColor);
+        mSnapshot = snapshot;
+        mTitle = title;
+        mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
+        mTaskBounds = taskBounds;
+        mSysUiVis = sysUiVis;
+        mWindowFlags = windowFlags;
+        mWindowPrivateFlags = windowPrivateFlags;
+        mSizeMismatch = (mFrame.width() != snapshot.getSnapshot().getWidth()
+                || mFrame.height() != snapshot.getSnapshot().getHeight());
+        mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
+                service.mContext.getColor(R.color.system_bar_background_semi_transparent),
+                statusBarColor);
+        mNavigationBarColor = navigationBarColor;
+        mStatusBarPaint.setColor(mStatusBarColor);
+        mNavigationBarPaint.setColor(navigationBarColor);
     }
 
     @Override
     public void remove() {
+        synchronized (mService.mWindowMap) {
+            final long now = SystemClock.uptimeMillis();
+            if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
+                mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
+                return;
+            }
+        }
         try {
             mSession.remove(mWindow);
         } catch (RemoteException e) {
@@ -150,31 +253,149 @@
         }
     }
 
-    private void drawSnapshot(GraphicBuffer snapshot) {
-        mSurface.attachAndQueueBuffer(snapshot);
+    @VisibleForTesting
+    void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
+        mFrame.set(frame);
+        mContentInsets.set(contentInsets);
+        mStableInsets.set(stableInsets);
+    }
+
+    private void drawSnapshot() {
+        final GraphicBuffer buffer = mSnapshot.getSnapshot();
+        if (mSizeMismatch) {
+            // The dimensions of the buffer and the window don't match, so attaching the buffer
+            // will fail. Better create a child window with the exact dimensions and fill the parent
+            // window with the background color!
+            drawSizeMismatchSnapshot(buffer);
+        } else {
+            drawSizeMatchSnapshot(buffer);
+        }
         final boolean reportNextDraw;
         synchronized (mService.mWindowMap) {
+            mShownTime = SystemClock.uptimeMillis();
             mHasDrawn = true;
             reportNextDraw = mReportNextDraw;
         }
         if (reportNextDraw) {
             reportDrawn();
         }
+    }
+
+    private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
+        mSurface.attachAndQueueBuffer(buffer);
+        mSurface.release();
+    }
+
+    private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+        final SurfaceSession session = new SurfaceSession(mSurface);
+
+        // Keep a reference to it such that it doesn't get destroyed when finalized.
+        mChildSurfaceControl = new SurfaceControl(session,
+                mTitle + " - task-snapshot-surface",
+                buffer.getWidth(), buffer.getHeight(), buffer.getFormat(), HIDDEN);
+        Surface surface = new Surface();
+        surface.copyFrom(mChildSurfaceControl);
+
+        // Clip off ugly navigation bar.
+        final Rect crop = calculateSnapshotCrop();
+        final Rect frame = calculateSnapshotFrame(crop);
+        SurfaceControl.openTransaction();
+        try {
+            // We can just show the surface here as it will still be hidden as the parent is
+            // still hidden.
+            mChildSurfaceControl.show();
+            mChildSurfaceControl.setWindowCrop(crop);
+            mChildSurfaceControl.setPosition(frame.left, frame.top);
+        } finally {
+            SurfaceControl.closeTransaction();
+        }
+        surface.attachAndQueueBuffer(buffer);
+        surface.release();
+
+        final Canvas c = mSurface.lockCanvas(null);
+        drawBackgroundAndBars(c, frame);
+        mSurface.unlockCanvasAndPost(c);
         mSurface.release();
     }
 
     @VisibleForTesting
-    void fillEmptyBackground(Canvas c, Bitmap b) {
-        final boolean fillHorizontally = c.getWidth() > b.getWidth();
-        final boolean fillVertically = c.getHeight() > b.getHeight();
+    Rect calculateSnapshotCrop() {
+        final Rect rect = new Rect();
+        rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight());
+        final Rect insets = mSnapshot.getContentInsets();
+
+        // Let's remove all system decorations except the status bar, but only if the task is at the
+        // very top of the screen.
+        rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom);
+        return rect;
+    }
+
+    @VisibleForTesting
+    Rect calculateSnapshotFrame(Rect crop) {
+        final Rect frame = new Rect(crop);
+
+        // By default, offset it to to top/left corner
+        frame.offsetTo(-crop.left, -crop.top);
+
+        // However, we also need to make space for the navigation bar on the left side.
+        final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
+                mContentInsets.left);
+        frame.offset(colorViewLeftInset, 0);
+        return frame;
+    }
+
+    @VisibleForTesting
+    void drawBackgroundAndBars(Canvas c, Rect frame) {
+        final int statusBarHeight = getStatusBarColorViewHeight();
+        final boolean fillHorizontally = c.getWidth() > frame.right;
+        final boolean fillVertically = c.getHeight() > frame.bottom;
         if (fillHorizontally) {
-            c.drawRect(b.getWidth(), 0, c.getWidth(), fillVertically
-                        ? b.getHeight()
-                        : c.getHeight(),
-                    mFillBackgroundPaint);
+            c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
+                    c.getWidth(), fillVertically
+                            ? frame.bottom
+                            : c.getHeight(),
+                    mBackgroundPaint);
         }
         if (fillVertically) {
-            c.drawRect(0, b.getHeight(), c.getWidth(), c.getHeight(), mFillBackgroundPaint);
+            c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
+        }
+        drawStatusBarBackground(c, frame, statusBarHeight);
+        drawNavigationBarBackground(c);
+    }
+
+    private int getStatusBarColorViewHeight() {
+        final boolean forceStatusBarBackground =
+                (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+        if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+                mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+            return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+        } else {
+            return 0;
+        }
+    }
+
+    private boolean isNavigationBarColorViewVisible() {
+        return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+                mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+    }
+
+    @VisibleForTesting
+    void drawStatusBarBackground(Canvas c, Rect frame, int statusBarHeight) {
+        if (statusBarHeight > 0 && c.getWidth() > frame.right) {
+            final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
+                    mContentInsets.right);
+            c.drawRect(frame.right, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+        }
+    }
+
+    @VisibleForTesting
+    void drawNavigationBarBackground(Canvas c) {
+        final Rect navigationBarRect = new Rect();
+        getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
+                navigationBarRect);
+        final boolean visible = isNavigationBarColorViewVisible();
+        if (visible && !navigationBarRect.isEmpty()) {
+            c.drawRect(navigationBarRect, mNavigationBarPaint);
         }
     }
 
@@ -211,10 +432,10 @@
         }
     };
 
-    private static class Window extends BaseIWindow {
+    @VisibleForTesting
+    static class Window extends BaseIWindow {
 
         private TaskSnapshotSurface mOuter;
-
         public void setOuter(TaskSnapshotSurface outer) {
             mOuter = outer;
         }
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 57fb81c..57eaa2b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -17,17 +17,15 @@
 package com.android.server.wm;
 
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
 
 import android.content.Context;
+import android.os.Handler;
 import android.os.Trace;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -36,6 +34,9 @@
 import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
+import com.android.server.DisplayThread;
+
 import java.io.PrintWriter;
 
 /**
@@ -82,20 +83,31 @@
     // check if some got replaced and can be removed.
     private boolean mRemoveReplacedWindows = false;
 
+    private long mCurrentFrameTime;
+    private final Runnable mAnimationTick;
+    private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
+
     WindowAnimator(final WindowManagerService service) {
         mService = service;
         mContext = service.mContext;
         mPolicy = service.mPolicy;
         mWindowPlacerLocked = service.mWindowPlacerLocked;
+        final Handler handler = DisplayThread.getHandler();
 
-        mAnimationFrameCallback = new Choreographer.FrameCallback() {
-            public void doFrame(long frameTimeNs) {
-                synchronized (mService.mWindowMap) {
-                    mService.mAnimationScheduled = false;
-                    animateLocked(frameTimeNs);
-                }
+        // TODO: Multi-display: If displays have different vsync tick, have a separate tick per
+        // display.
+        mSfChoreographer = new SurfaceFlingerVsyncChoreographer(handler,
+                mService.getDefaultDisplayContentLocked().getDisplay());
+        mAnimationTick = () -> {
+            synchronized (mService.mWindowMap) {
+                mService.mAnimationScheduled = false;
+                animateLocked(mCurrentFrameTime);
             }
         };
+        mAnimationFrameCallback = frameTimeNs -> {
+            mCurrentFrameTime = frameTimeNs;
+            mSfChoreographer.scheduleAtSfVsync(mAnimationTick);
+        };
     }
 
     void addDisplayLocked(final int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowContainerController.java b/services/core/java/com/android/server/wm/WindowContainerController.java
index 84ffc35..c4a6837 100644
--- a/services/core/java/com/android/server/wm/WindowContainerController.java
+++ b/services/core/java/com/android/server/wm/WindowContainerController.java
@@ -33,7 +33,7 @@
 
     final WindowManagerService mService;
     final RootWindowContainer mRoot;
-    final HashMap<IBinder, WindowState> mWindowMap;
+    final WindowHashMap mWindowMap;
 
     // The window container this controller owns.
     E mContainer;
diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/services/core/java/com/android/server/wm/WindowHashMap.java
similarity index 65%
rename from core/java/com/android/internal/font/IFontManager.aidl
rename to services/core/java/com/android/server/wm/WindowHashMap.java
index 52a6262..49bba41 100644
--- a/core/java/com/android/internal/font/IFontManager.aidl
+++ b/services/core/java/com/android/server/wm/WindowHashMap.java
@@ -11,17 +11,18 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.internal.font;
+package com.android.server.wm;
 
-import android.text.FontConfig;
+import android.os.IBinder;
+
+import java.util.HashMap;
 
 /**
- * Interface to the font manager.
- * @hide
+ * Subclass of HashMap such that we can instruct the compiler to boost our thread priority when
+ * locking this class. See makefile.
  */
-interface IFontManager {
-    FontConfig getSystemFonts();
+class WindowHashMap extends HashMap<IBinder, WindowState> {
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 95fbbb8..1be0512 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
+import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -25,6 +26,11 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.EXTRA_USER_HANDLE;
+import static android.os.Process.ROOT_UID;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+import static android.os.Process.myPid;
 import static android.os.UserHandle.USER_NULL;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -60,6 +66,8 @@
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.LockGuard.INDEX_WINDOW;
+import static com.android.server.LockGuard.installLock;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END;
 import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START;
@@ -102,6 +110,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.content.BroadcastReceiver;
@@ -124,7 +133,6 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputManager;
 import android.net.Uri;
-import android.os.PowerSaveState;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -138,7 +146,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
-import android.os.Process;
+import android.os.PowerSaveState;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -150,10 +158,10 @@
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.util.ArraySet;
-import android.util.MergedConfiguration;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.MergedConfiguration;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -214,7 +222,7 @@
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
-import com.android.server.LockGuard;
+import com.android.server.ThreadPriorityBooster;
 import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.input.InputManagerService;
@@ -238,10 +246,7 @@
 import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
-
-import static android.Manifest.permission.READ_FRAME_BUFFER;
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@@ -407,7 +412,7 @@
      * This is also used as the lock for all of our state.
      * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
      */
-    final HashMap<IBinder, WindowState> mWindowMap = new HashMap<>();
+    final WindowHashMap mWindowMap = new WindowHashMap();
 
     /**
      * List of window tokens that have finished starting their application,
@@ -847,6 +852,16 @@
     // since they won't be notified through the app window animator.
     final List<IBinder> mNoAnimationNotifyOnTransitionFinished = new ArrayList<>();
 
+    private static ThreadPriorityBooster sThreadPriorityBooster = new ThreadPriorityBooster(
+            THREAD_PRIORITY_DISPLAY, INDEX_WINDOW);
+
+    static void boostPriorityForLockedSection() {
+        sThreadPriorityBooster.boost();
+    }
+
+    static void resetPriorityAfterLockedSection() {
+        sThreadPriorityBooster.reset();
+    }
 
     void openSurfaceTransaction() {
         synchronized (mWindowMap) {
@@ -935,7 +950,7 @@
     private WindowManagerService(Context context, InputManagerService inputManager,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
             WindowManagerPolicy policy) {
-        LockGuard.installLock(this, LockGuard.INDEX_WINDOW);
+        installLock(this, INDEX_WINDOW);
         mRoot = new RootWindowContainer(this);
         mContext = context;
         mHaveInputMethods = haveInputMethods;
@@ -1580,7 +1595,7 @@
     @Override
     public void enableSurfaceTrace(ParcelFileDescriptor pfd) {
         final int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+        if (callingUid != SHELL_UID && callingUid != ROOT_UID) {
             throw new SecurityException("Only shell can call enableSurfaceTrace");
         }
 
@@ -1592,8 +1607,8 @@
     @Override
     public void disableSurfaceTrace() {
         final int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID &&
-            callingUid != Process.SYSTEM_UID) {
+        if (callingUid != SHELL_UID && callingUid != ROOT_UID &&
+            callingUid != SYSTEM_UID) {
             throw new SecurityException("Only shell can call disableSurfaceTrace");
         }
         synchronized (mWindowMap) {
@@ -1607,7 +1622,7 @@
     @Override
     public void setScreenCaptureDisabled(int userId, boolean disabled) {
         int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.SYSTEM_UID) {
+        if (callingUid != SYSTEM_UID) {
             throw new SecurityException("Only system can call setScreenCaptureDisabled.");
         }
 
@@ -2263,7 +2278,7 @@
 
     boolean checkCallingPermission(String permission, String func) {
         // Quick check: if the calling permission is me, it's all okay.
-        if (Binder.getCallingPid() == Process.myPid()) {
+        if (Binder.getCallingPid() == myPid()) {
             return true;
         }
 
@@ -2916,7 +2931,7 @@
         }
         // If this isn't coming from the system then don't allow disabling the lockscreen
         // to bypass security.
-        if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) {
+        if (Binder.getCallingUid() != SYSTEM_UID && isKeyguardSecure()) {
             Log.d(TAG_WM, "current mode is SecurityMode, ignore disableKeyguard");
             return;
         }
@@ -3196,19 +3211,25 @@
     // Called by window manager policy.  Not exposed externally.
     @Override
     public void shutdown(boolean confirm) {
-        ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+        // Pass in the UI context, since ShutdownThread requires it (to show UI).
+        ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
+                PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
     }
 
     // Called by window manager policy.  Not exposed externally.
     @Override
     public void reboot(boolean confirm) {
-        ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
+        // Pass in the UI context, since ShutdownThread requires it (to show UI).
+        ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(),
+                PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
     }
 
     // Called by window manager policy.  Not exposed externally.
     @Override
     public void rebootSafeMode(boolean confirm) {
-        ShutdownThread.rebootSafeMode(mContext, confirm);
+        // Pass in the UI context, since ShutdownThread requires it (to show UI).
+        ShutdownThread.rebootSafeMode(ActivityThread.currentActivityThread().getSystemUiContext(),
+                confirm);
     }
 
     public void setCurrentProfileIds(final int[] currentProfileIds) {
@@ -5312,8 +5333,8 @@
                     if (displayContent.mBaseDisplayWidth != width
                             || displayContent.mBaseDisplayHeight != height) {
                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
-                        displayContent.mBaseDisplayWidth = width;
-                        displayContent.mBaseDisplayHeight = height;
+                        displayContent.updateBaseDisplayMetrics(width, height,
+                                displayContent.mBaseDisplayDensity);
                     }
                 } catch (NumberFormatException ex) {
                 }
@@ -5338,8 +5359,7 @@
     // displayContent must not be null
     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
-        displayContent.mBaseDisplayWidth = width;
-        displayContent.mBaseDisplayHeight = height;
+        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
         reconfigureDisplayLocked(displayContent);
     }
 
@@ -7052,7 +7072,7 @@
                     throw new IllegalStateException("Magnification callbacks not set!");
                 }
             }
-            if (Binder.getCallingPid() != android.os.Process.myPid()) {
+            if (Binder.getCallingPid() != myPid()) {
                 spec.recycle();
             }
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6fd95a4..8098eea 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2395,6 +2395,9 @@
         if (requestAnim) {
             mService.scheduleAnimationLocked();
         }
+        if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) {
+            mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
+        }
         return true;
     }
 
@@ -2437,6 +2440,9 @@
         if (requestAnim) {
             mService.scheduleAnimationLocked();
         }
+        if (mService.mCurrentFocus == this) {
+            mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
+        }
         return true;
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index da49eb3..a5eac46 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -475,6 +475,9 @@
         ActivityThread activityThread = ActivityThread.systemMain();
         mSystemContext = activityThread.getSystemContext();
         mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
+
+        final Context systemUiContext = activityThread.getSystemUiContext();
+        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
     }
 
     /**
@@ -1014,12 +1017,6 @@
                 traceEnd();
             }
 
-            if (!disableNonCoreServices) {
-                traceBeginAndSlog("StartFontServiceManager");
-                mSystemServiceManager.startService(FontManagerService.Lifecycle.class);
-                traceEnd();
-            }
-
             if (!disableNonCoreServices && !disableTextServices) {
                 traceBeginAndSlog("StartTextServicesManager");
                 mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
diff --git a/services/profile-classes b/services/profile-classes
index 1b304e1..b0d2da7 100644
--- a/services/profile-classes
+++ b/services/profile-classes
@@ -2481,7 +2481,6 @@
 Landroid/text/FontConfig$Family$1;
 Landroid/text/FontConfig$Font;
 Landroid/text/FontConfig$Font$1;
-Landroid/text/FontManager;
 Landroid/text/format/DateFormat;
 Landroid/text/format/Time;
 Landroid/text/format/Time$TimeCalculator;
@@ -3132,8 +3131,6 @@
 Lcom/android/internal/content/PackageMonitor;
 Lcom/android/internal/content/ReferrerIntent;
 Lcom/android/internal/content/ReferrerIntent$1;
-Lcom/android/internal/font/IFontManager;
-Lcom/android/internal/font/IFontManager$Stub;
 Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable;
 Lcom/android/internal/graphics/drawable/AnimationScaleListDrawable$AnimationScaleListState;
 Lcom/android/internal/hardware/AmbientDisplayConfiguration;
@@ -4377,8 +4374,6 @@
 Lcom/android/server/firewall/StringFilter$8;
 Lcom/android/server/firewall/StringFilter$9;
 Lcom/android/server/firewall/StringFilter$ValueProvider;
-Lcom/android/server/FontManagerService;
-Lcom/android/server/FontManagerService$Lifecycle;
 Lcom/android/server/GestureLauncherService;
 Lcom/android/server/GestureLauncherService$1;
 Lcom/android/server/GestureLauncherService$2;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 9197ccf9..0694eae 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -22,6 +22,7 @@
 import static junit.framework.Assert.assertTrue;
 
 import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
@@ -170,6 +171,7 @@
         mockScoreNetworksGranted(recoComponent.getPackageName());
         mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
                 enableUseOpenWifiComponent.getPackageName());
+        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
@@ -350,6 +352,173 @@
                 eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
     }
 
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerAppIsNull()
+            throws Exception {
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP)).thenReturn(null);
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerAppIsEmpty()
+            throws Exception {
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP)).thenReturn("");
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerIsNotActive()
+            throws Exception {
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP)).thenReturn("com.foo.package");
+        // Make getActiveScorer() return null.
+        setRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiSettingIsNotEmpty()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                enableUseOpenWifiComponent.getPackageName());
+        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP))
+                .thenReturn(enableUseOpenWifiComponent.getPackageName());
+        // The setting has a value so the migration shouldn't touch it.
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.USE_OPEN_WIFI_PACKAGE))
+                .thenReturn(enableUseOpenWifiComponent.getPackageName());
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+        verify(mSettingsFacade).putString(eq(mMockContext),
+                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiActivityNotAvail()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        // The active component doesn't have an open wifi activity so the migration shouldn't
+        // set USE_OPEN_WIFI_PACKAGE.
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                null /*useOpenWifiActivityPackage*/);
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP))
+                .thenReturn(enableUseOpenWifiComponent.getPackageName());
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+        verify(mSettingsFacade).putString(eq(mMockContext),
+                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_activity()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                enableUseOpenWifiComponent.getPackageName());
+        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+        // The older network scorer app setting doesn't match the new use open wifi activity package
+        // so the migration shouldn't set USE_OPEN_WIFI_PACKAGE.
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP))
+                .thenReturn(enableUseOpenWifiComponent.getPackageName() + ".diff");
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+        verify(mSettingsFacade).putString(eq(mMockContext),
+                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_service()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                enableUseOpenWifiComponent.getPackageName());
+        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+        // The older network scorer app setting doesn't match the active package so the migration
+        // shouldn't set USE_OPEN_WIFI_PACKAGE.
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP))
+                .thenReturn(recoComponent.getPackageName() + ".diff");
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade, never()).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
+        verify(mSettingsFacade).putString(eq(mMockContext),
+                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+    }
+
+    @Test
+    public void testMigrateNetworkScorerAppSettingIfNeeded_packageMatch_activity()
+            throws Exception {
+        final ComponentName recoComponent = new ComponentName("package1", "class1");
+        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
+        setNetworkRecoPackageSetting(recoComponent.getPackageName());
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+                enableUseOpenWifiComponent.getPackageName());
+        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
+        // Old setting matches the new activity package, migration should happen.
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.NETWORK_SCORER_APP))
+                .thenReturn(enableUseOpenWifiComponent.getPackageName());
+        when(mSettingsFacade.getString(mMockContext,
+                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
+
+        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
+
+        verify(mSettingsFacade).putString(eq(mMockContext),
+                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE),
+                eq(enableUseOpenWifiComponent.getPackageName()));
+        verify(mSettingsFacade).putString(eq(mMockContext),
+                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
+    }
+
     private void setRecommendationsEnabledSetting(int value) {
         when(mSettingsFacade.getInt(eq(mMockContext),
                 eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt())).thenReturn(value);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index aa37407..5d0c23f 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -149,7 +149,7 @@
         // 2nd account
         Account account2 = new Account("name", "example2.com");
         long accId2 = mAccountsDb.insertCeAccount(account2, "password");
-        mAccountsDb.insertDeAccount(account2, accId);
+        mAccountsDb.insertDeAccount(account2, accId2);
         mAccountsDb.insertAuthToken(accId2, "type", "token");
 
         mAccountsDb.deleteAuthTokensByAccountId(accId2);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
new file mode 100644
index 0000000..54ecab3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link ActivityRecord} class.
+ *
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityRecordTests extends ActivityTestsBase {
+    private final ComponentName testActivityComponent =
+            ComponentName.unflattenFromString("com.foo/.BarActivity");
+    @Test
+    public void testStackCleanupOnClearingTask() throws Exception {
+        final ActivityManagerService service = createActivityManagerService();
+        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+        record.setTask(null);
+        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+    }
+
+    @Test
+    public void testStackCleanupOnActivityRemoval() throws Exception {
+        final ActivityManagerService service = createActivityManagerService();
+        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+        task.removeActivity(record);
+        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+    }
+
+    @Test
+    public void testStackCleanupOnTaskRemoval() throws Exception {
+        final ActivityManagerService service = createActivityManagerService();
+        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final ActivityRecord record = createActivity(service, testActivityComponent, task);
+
+        testStack.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
+        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+    }
+
+    @Test
+    public void testNoCleanupMovingActivityInSameStack() throws Exception {
+        final ActivityManagerService service = createActivityManagerService();
+        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+        final TaskRecord oldTask = createTask(service, testActivityComponent, testStack);
+        final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
+        final TaskRecord newTask = createTask(service, testActivityComponent, testStack);
+
+        record.reparent(newTask, 0, null /*reason*/);
+        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
new file mode 100644
index 0000000..b59c2bc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertNull;
+
+import android.os.Debug;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+
+/**
+ * Tests for the {@link ActivityStackSupervisor} class.
+ *
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityStackSupervisorTests extends ActivityTestsBase {
+    /**
+     * This test ensures that we do not try to restore a task based off an invalid task id. The
+     * stack supervisor is a test version so there will be no tasks present. We should expect
+     * {@code null} to be returned in this case.
+     */
+    @Test
+    public void testRestoringInvalidTask() throws Exception {
+        Debug.waitForDebugger();
+        final ActivityManagerService service = createActivityManagerService();
+        TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
+                MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
+        assertNull(task);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
new file mode 100644
index 0000000..5240586
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import com.android.server.AttributeCache;
+import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.StackWindowController;
+
+import com.android.server.wm.WindowManagerService;
+import com.android.server.wm.WindowTestUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * A base class to handle common operations in activity related unit tests.
+ */
+public class ActivityTestsBase {
+    private final Context mContext = InstrumentationRegistry.getContext();
+    private HandlerThread mHandlerThread;
+
+    // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
+    // be called at before any tests.
+    private final WindowManagerService mWms = WindowTestUtils.getWindowManagerService(mContext);
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
+        mHandlerThread.start();
+    }
+
+    @After
+    public void tearDown() {
+        mHandlerThread.quitSafely();
+    }
+
+    protected ActivityManagerService createActivityManagerService() {
+        return new TestActivityManagerService(mContext);
+    }
+
+    protected static TestActivityStack createActivityStack(ActivityManagerService service,
+            int stackId, int displayId, boolean onTop) {
+        if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
+            final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
+                    .createTestStack(stackId, onTop);
+            return stack;
+        }
+
+        return null;
+    }
+
+    protected static ActivityRecord createActivity(ActivityManagerService service,
+            ComponentName component, TaskRecord task) {
+        Intent intent = new Intent();
+        intent.setComponent(component);
+        final ActivityInfo aInfo = new ActivityInfo();
+        aInfo.applicationInfo = new ApplicationInfo();
+        aInfo.applicationInfo.packageName = component.getPackageName();
+        AttributeCache.init(service.mContext);
+        final ActivityRecord activity = new ActivityRecord(service, null /* caller */,
+                0 /* launchedFromPid */, 0, null, intent, null,
+                aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
+                0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
+                service.mStackSupervisor, null /* container */, null /* options */,
+                null /* sourceRecord */);
+        activity.mWindowContainerController = mock(AppWindowContainerController.class);
+
+        if (task != null) {
+            task.addActivityToTop(activity);
+        }
+
+        return activity;
+    }
+
+    protected static TaskRecord createTask(ActivityManagerService service,
+            ComponentName component, ActivityStack stack) {
+        final ActivityInfo aInfo = new ActivityInfo();
+        aInfo.applicationInfo = new ApplicationInfo();
+        aInfo.applicationInfo.packageName = component.getPackageName();
+
+        Intent intent = new Intent();
+        intent.setComponent(component);
+
+        final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
+                null /*_taskDescription*/, null /*thumbnailInfo*/);
+        stack.addTask(task, true, "creating test task");
+        task.setStack(stack);
+        task.createWindowContainer(true, true);
+
+        return task;
+    }
+
+    /**
+     * An {@link ActivityManagerService} subclass which provides a test
+     * {@link ActivityStackSupervisor}.
+     */
+    protected static class TestActivityManagerService extends ActivityManagerService {
+        public TestActivityManagerService(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected ActivityStackSupervisor createStackSupervisor() {
+            return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
+        }
+    }
+
+    /**
+     * An {@link ActivityStackSupervisor} which stubs out certain methods that depend on
+     * setup not available in the test environment. Also specifies an injector for
+     */
+    protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
+        public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
+            super(service, looper);
+        }
+
+        // Invoked during {@link ActivityStack} creation.
+        @Override
+        void updateUIDsPresentOnDisplay() {
+        }
+
+        public TestActivityStack createTestStack(int stackId, boolean onTop) {
+            final ActivityDisplay display = new ActivityDisplay();
+            final TestActivityContainer container =
+                    new TestActivityContainer(stackId, display, onTop);
+            return container.getStack();
+        }
+
+        private class TestActivityContainer extends ActivityContainer {
+            private TestActivityStack mStack;
+            TestActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) {
+                super(stackId, activityDisplay, onTop);
+            }
+
+            @Override
+            protected void createStack(int stackId, boolean onTop) {
+                mStack = new TestActivityStack(this, null /*recentTasks*/, onTop);
+            }
+
+            public TestActivityStack getStack() {
+                return mStack;
+            }
+        }
+    }
+
+    /**
+     * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
+     * method is called. Note that its functionality depends on the implementations of the
+     * construction arguments.
+     */
+    protected static class TestActivityStack<T extends StackWindowController>
+            extends ActivityStack<T> {
+        private int mOnActivityRemovedFromStackCount = 0;
+        private T mContainerController;
+        TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
+                RecentTasks recentTasks, boolean onTop) {
+            super(activityContainer, recentTasks, onTop);
+        }
+
+        @Override
+        void onActivityRemovedFromStack(ActivityRecord r) {
+            mOnActivityRemovedFromStackCount++;
+            super.onActivityRemovedFromStack(r);
+        }
+
+        // Returns the number of times {@link #onActivityRemovedFromStack} has been called
+        public int onActivityRemovedFromStackInvocationCount() {
+            return mOnActivityRemovedFromStackCount;
+        }
+
+        @Override
+        protected T createStackWindowController(int displayId, boolean onTop,
+                Rect outBounds) {
+            mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
+            return mContainerController;
+        }
+
+        @Override
+        T getWindowContainerController() {
+            return mContainerController;
+        }
+    }
+
+    protected static class ActivityStackBuilder {
+        private boolean mOnTop = true;
+        private int mStackId = 0;
+        private int mDisplayId = 1;
+
+        private final ActivityManagerService mService;
+
+        public ActivityStackBuilder(ActivityManagerService ams) {
+            mService = ams;
+        }
+
+        public ActivityStackBuilder setOnTop(boolean onTop) {
+            mOnTop = onTop;
+            return this;
+        }
+
+        public ActivityStackBuilder setStackId(int id) {
+            mStackId = id;
+            return this;
+        }
+
+        public ActivityStackBuilder setDisplayId(int id) {
+            mDisplayId = id;
+            return this;
+        }
+
+        public TestActivityStack build() {
+            return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f3f68ff..2663aaf 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -50,6 +50,7 @@
 
 import org.mockito.ArgumentCaptor;
 
+import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
@@ -249,6 +250,25 @@
         assertEquals(7, updates.size());
     }
 
+    public void testGetInstalledProvidersForPackage() {
+        List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
+        assertTrue(!allProviders.isEmpty());
+        String packageName = allProviders.get(0).provider.getPackageName();
+        List<AppWidgetProviderInfo> providersForPackage = mManager.getInstalledProvidersForPackage(
+                packageName, null);
+        // Remove providers from allProviders that don't have the given package name.
+        Iterator<AppWidgetProviderInfo> iter = allProviders.iterator();
+        while (iter.hasNext()) {
+            if (!iter.next().provider.getPackageName().equals(packageName)) {
+                iter.remove();
+            }
+        }
+        assertEquals(allProviders.size(), providersForPackage.size());
+        for (int i = 0; i < allProviders.size(); i++) {
+            assertEquals(allProviders.get(i).provider, providersForPackage.get(i).provider);
+        }
+    }
+
     private int setupHostAndWidget() {
         List<PendingHostUpdate> updates = mService.startListening(
                 mMockHost, mPkgName, HOST_ID, new int[0]).getList();
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 2ccaefc..25004de 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -44,7 +44,8 @@
 
     @Test
     public void testRemoveContainer() throws Exception {
-        final TestAppWindowContainerController controller = createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller =
+                createAppWindowController();
 
         // Assert token was added to display.
         assertNotNull(sDisplayContent.getWindowToken(controller.mToken.asBinder()));
@@ -61,7 +62,8 @@
 
     @Test
     public void testSetOrientation() throws Exception {
-        final TestAppWindowContainerController controller = createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller =
+                createAppWindowController();
 
         // Assert orientation is unspecified to start.
         assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation());
@@ -92,7 +94,8 @@
 
     @Test
     public void testCreateRemoveStartingWindow() throws Exception {
-        final TestAppWindowContainerController controller = createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller =
+                createAppWindowController();
         controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
         waitUntilHandlerIdle();
@@ -105,8 +108,10 @@
 
     @Test
     public void testTransferStartingWindow() throws Exception {
-        final TestAppWindowContainerController controller1 = createAppWindowController();
-        final TestAppWindowContainerController controller2 = createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller1 =
+                createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller2 =
+                createAppWindowController();
         controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
                 android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
         waitUntilHandlerIdle();
@@ -120,8 +125,10 @@
 
     @Test
     public void testTransferStartingWindowWhileCreating() throws Exception {
-        final TestAppWindowContainerController controller1 = createAppWindowController();
-        final TestAppWindowContainerController controller2 = createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller1 =
+                createAppWindowController();
+        final WindowTestUtils.TestAppWindowContainerController controller2 =
+                createAppWindowController();
         sPolicy.setRunnableWhenAddingSplashScreen(() -> {
 
             // Surprise, ...! Transfer window in the middle of the creation flow.
@@ -140,16 +147,16 @@
     public void testReparent() throws Exception {
         final StackWindowController stackController =
             createStackControllerOnDisplay(sDisplayContent);
-        final TestTaskWindowContainerController taskController1 =
-                new TestTaskWindowContainerController(stackController);
-        final TestAppWindowContainerController appWindowController1 = createAppWindowController(
-                taskController1);
-        final TestTaskWindowContainerController taskController2 =
-                new TestTaskWindowContainerController(stackController);
-        final TestAppWindowContainerController appWindowController2 = createAppWindowController(
-                taskController2);
-        final TestTaskWindowContainerController taskController3 =
-                new TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestTaskWindowContainerController taskController1 =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestAppWindowContainerController appWindowController1 =
+                createAppWindowController(taskController1);
+        final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestAppWindowContainerController appWindowController2 =
+                createAppWindowController(taskController2);
+        final WindowTestUtils.TestTaskWindowContainerController taskController3 =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController);
 
         try {
             appWindowController1.reparent(taskController1, 0);
@@ -169,16 +176,18 @@
         // Reparent the app window and ensure that it is moved
         appWindowController1.reparent(taskController2, 0);
         assertEquals(taskController2.mContainer, appWindowController1.mContainer.getParent());
-        assertEquals(0, ((TestAppWindowToken) appWindowController1.mContainer).positionInParent());
-        assertEquals(1, ((TestAppWindowToken) appWindowController2.mContainer).positionInParent());
+        assertEquals(0, ((WindowTestUtils.TestAppWindowToken) appWindowController1.mContainer)
+                .positionInParent());
+        assertEquals(1, ((WindowTestUtils.TestAppWindowToken) appWindowController2.mContainer)
+                .positionInParent());
     }
 
-    private TestAppWindowContainerController createAppWindowController() {
-        return createAppWindowController(new TestTaskWindowContainerController());
+    private WindowTestUtils.TestAppWindowContainerController createAppWindowController() {
+        return createAppWindowController(new WindowTestUtils.TestTaskWindowContainerController());
     }
 
-    private TestAppWindowContainerController createAppWindowController(
-            TestTaskWindowContainerController taskController) {
-        return new TestAppWindowContainerController(taskController);
+    private WindowTestUtils.TestAppWindowContainerController createAppWindowController(
+            WindowTestUtils.TestTaskWindowContainerController taskController) {
+        return new WindowTestUtils.TestAppWindowContainerController(taskController);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 2003b91..7a7ca3f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -51,7 +51,8 @@
 
     @Test
     public void testAddWindow_Order() throws Exception {
-        final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final WindowTestUtils.TestAppWindowToken token =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
 
         assertEquals(0, token.getWindowsCount());
 
@@ -78,7 +79,8 @@
 
     @Test
     public void testFindMainWindow() throws Exception {
-        final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final WindowTestUtils.TestAppWindowToken token =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
 
         assertNull(token.findMainWindow());
 
@@ -102,12 +104,13 @@
         // Create an app window with token on a display.
         final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final TestAppWindowToken appWindowToken = new TestAppWindowToken(sDisplayContent);
+        final WindowTestUtils.TestAppWindowToken appWindowToken =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         task.addChild(appWindowToken, 0);
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
-        final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken);
         appWindowToken.addWindow(appWindow);
 
         // Set initial orientation and update.
@@ -137,12 +140,13 @@
         final DisplayContent defaultDisplayContent = sWm.getDefaultDisplayContentLocked();
         final TaskStack stack = createTaskStackOnDisplay(defaultDisplayContent);
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final TestAppWindowToken appWindowToken = new TestAppWindowToken(defaultDisplayContent);
+        final WindowTestUtils.TestAppWindowToken appWindowToken =
+                new WindowTestUtils.TestAppWindowToken(defaultDisplayContent);
         task.addChild(appWindowToken, 0);
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                 TYPE_BASE_APPLICATION);
         attrs.setTitle("AppWindow");
-        final TestWindowState appWindow = new TestWindowState(attrs, appWindowToken);
+        final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, appWindowToken);
         appWindowToken.addWindow(appWindow);
 
         // Set initial orientation and update.
@@ -165,7 +169,8 @@
 
     @Test
     public void testGetOrientation() throws Exception {
-        final TestAppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final WindowTestUtils.TestAppWindowToken token =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         token.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         token.setFillsParent(false);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index e3ccd6e..d7d365e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -175,7 +175,7 @@
         assertEquals(dc, stack.getDisplayContent());
 
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final TestAppWindowToken token = new TestAppWindowToken(dc);
+        final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
         task.addChild(token, 0);
         assertEquals(dc, task.getDisplayContent());
         assertEquals(dc, token.getDisplayContent());
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
index b0eba0b..13098f6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -16,12 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
 import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
-import android.view.Display;
-import android.view.DisplayInfo;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -48,8 +43,8 @@
     public void testRemoveContainer() throws Exception {
         final StackWindowController stackController =
                 createStackControllerOnDisplay(sDisplayContent);
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController);
 
         final TaskStack stack = stackController.mContainer;
         final Task task = taskController.mContainer;
@@ -68,11 +63,11 @@
     public void testRemoveContainer_deferRemoval() throws Exception {
         final StackWindowController stackController =
                 createStackControllerOnDisplay(sDisplayContent);
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController(stackController);
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController);
 
         final TaskStack stack = stackController.mContainer;
-        final TestTask task = (TestTask) taskController.mContainer;
+        final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
         // Stack removal is deferred if one of its child is animating.
         task.setLocalIsAnimating(true);
 
@@ -96,9 +91,9 @@
         final StackWindowController stack1Controller =
                 createStackControllerOnDisplay(sDisplayContent);
         final TaskStack stack1 = stack1Controller.mContainer;
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController(stack1Controller);
-        final TestTask task1 = (TestTask) taskController.mContainer;
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
+        final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
         task1.mOnDisplayChangedCalled = false;
 
         // Create second display and put second stack on it.
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index aab75ee..717ddf2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
@@ -24,15 +27,19 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
+import android.app.ActivityManager.TaskSnapshot;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.view.Surface;
 
-import org.junit.Before;
+import com.android.server.wm.TaskSnapshotSurface.Window;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -48,59 +55,174 @@
 
     private TaskSnapshotSurface mSurface;
 
-    @Before
-    public void setUp() {
-        mSurface = new TaskSnapshotSurface(null, null, null, Color.WHITE);
+    private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
+            int windowFlags, Rect taskBounds) {
+        final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
+                GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+        final TaskSnapshot snapshot = new TaskSnapshot(buffer,
+                ORIENTATION_PORTRAIT, contentInsets, false, 1.0f);
+        mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
+                Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds);
+    }
+
+    private void setupSurface(int width, int height) {
+        setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, width, height));
     }
 
     @Test
     public void fillEmptyBackground_fillHorizontally() throws Exception {
+        setupSurface(200, 100);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(200);
         when(mockCanvas.getHeight()).thenReturn(100);
-        final Bitmap b = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
-        mSurface.fillEmptyBackground(mockCanvas, b);
+        mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
         verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
     }
 
     @Test
     public void fillEmptyBackground_fillVertically() throws Exception {
+        setupSurface(100, 200);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(200);
-        final Bitmap b = Bitmap.createBitmap(200, 100, Config.ARGB_8888);
-        mSurface.fillEmptyBackground(mockCanvas, b);
+        mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
         verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
     }
 
     @Test
     public void fillEmptyBackground_fillBoth() throws Exception {
+        setupSurface(200, 200);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(200);
         when(mockCanvas.getHeight()).thenReturn(200);
-        final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
-        mSurface.fillEmptyBackground(mockCanvas, b);
+        mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
         verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
         verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
     }
 
     @Test
     public void fillEmptyBackground_dontFill_sameSize() throws Exception {
+        setupSurface(100, 100);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
-        mSurface.fillEmptyBackground(mockCanvas, b);
+        mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
         verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
     }
 
     @Test
     public void fillEmptyBackground_dontFill_bitmapLarger() throws Exception {
+        setupSurface(100, 100);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        final Bitmap b = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
-        mSurface.fillEmptyBackground(mockCanvas, b);
+        mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
         verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
     }
+
+    @Test
+    public void testCalculateSnapshotCrop() {
+        setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(0, 0, 100, 90), mSurface.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_taskNotOnTop() {
+        setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 100));
+        assertEquals(new Rect(0, 10, 100, 90), mSurface.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_navBarLeft() {
+        setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(10, 0, 100, 100), mSurface.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotCrop_navBarRight() {
+        setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
+        assertEquals(new Rect(0, 0, 90, 100), mSurface.calculateSnapshotCrop());
+    }
+
+    @Test
+    public void testCalculateSnapshotFrame() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 0, 10);
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        assertEquals(new Rect(0, -10, 100, 70),
+                mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
+    }
+
+    @Test
+    public void testCalculateSnapshotFrame_navBarLeft() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(10, 10, 0, 0);
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        assertEquals(new Rect(0, -10, 90, 80),
+                mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
+    }
+
+    @Test
+    public void testDrawStatusBarBackground() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 10, 0);
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100), 10);
+        verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+    }
+
+    @Test
+    public void testDrawStatusBarBackground_nope() {
+        setupSurface(100, 100);
+        final Rect insets = new Rect(0, 10, 10, 0);
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100), 10);
+        verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+    }
+
+    @Test
+    public void testDrawNavigationBarBackground() {
+        final Rect insets = new Rect(0, 10, 0, 10);
+        setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, 100, 100));
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mSurface.drawNavigationBarBackground(mockCanvas);
+        verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
+    }
+
+    @Test
+    public void testDrawNavigationBarBackground_left() {
+        final Rect insets = new Rect(10, 10, 0, 0);
+        setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, 100, 100));
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mSurface.drawNavigationBarBackground(mockCanvas);
+        verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
+    }
+
+    @Test
+    public void testDrawNavigationBarBackground_right() {
+        final Rect insets = new Rect(0, 10, 10, 0);
+        setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+                new Rect(0, 0, 100, 100));
+        mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+        final Canvas mockCanvas = mock(Canvas.class);
+        when(mockCanvas.getWidth()).thenReturn(100);
+        when(mockCanvas.getHeight()).thenReturn(100);
+        mSurface.drawNavigationBarBackground(mockCanvas);
+        verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
index 462bd68..82ea2313 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -56,7 +56,7 @@
         // Stack should contain visible app window to be considered visible.
         final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
         assertFalse(mPinnedStack.isVisible());
-        final TestAppWindowToken pinnedApp = new TestAppWindowToken(sDisplayContent);
+        final WindowTestUtils.TestAppWindowToken pinnedApp = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         pinnedTask.addChild(pinnedApp, 0 /* addPos */);
         assertTrue(mPinnedStack.isVisible());
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
index 9dbd8a6..267e5f7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
@@ -16,9 +16,6 @@
 
 package com.android.server.wm;
 
-import android.content.pm.ActivityInfo;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -67,12 +64,14 @@
     public void testClosingAppDifferentStackOrientation() throws Exception {
         final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        TestAppWindowToken appWindowToken1 = new TestAppWindowToken(sDisplayContent);
+        WindowTestUtils.TestAppWindowToken appWindowToken1 =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         task1.addChild(appWindowToken1, 0);
         appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        TestAppWindowToken appWindowToken2 = new TestAppWindowToken(sDisplayContent);
+        WindowTestUtils.TestAppWindowToken appWindowToken2 =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         task2.addChild(appWindowToken2, 0);
         appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
@@ -85,12 +84,14 @@
     public void testMoveTaskToBackDifferentStackOrientation() throws Exception {
         final TaskStack stack = createTaskStackOnDisplay(sDisplayContent);
         final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        TestAppWindowToken appWindowToken1 = new TestAppWindowToken(sDisplayContent);
+        WindowTestUtils.TestAppWindowToken appWindowToken1 =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         task1.addChild(appWindowToken1, 0);
         appWindowToken1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        TestAppWindowToken appWindowToken2 = new TestAppWindowToken(sDisplayContent);
+        WindowTestUtils.TestAppWindowToken appWindowToken2 =
+                new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         task2.addChild(appWindowToken2, 0);
         appWindowToken2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index f79908e..1819c56 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -16,14 +16,9 @@
 
 package com.android.server.wm;
 
-import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
-
-import android.hardware.display.DisplayManagerGlobal;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.view.Display;
-import android.view.DisplayInfo;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -45,10 +40,10 @@
 
     @Test
     public void testRemoveContainer() throws Exception {
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController();
-        final TestAppWindowContainerController appController =
-                new TestAppWindowContainerController(taskController);
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController();
+        final WindowTestUtils.TestAppWindowContainerController appController =
+                new WindowTestUtils.TestAppWindowContainerController(taskController);
 
         taskController.removeContainer();
         // Assert that the container was removed.
@@ -58,12 +53,12 @@
 
     @Test
     public void testRemoveContainer_deferRemoval() throws Exception {
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController();
-        final TestAppWindowContainerController appController =
-                new TestAppWindowContainerController(taskController);
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController();
+        final WindowTestUtils.TestAppWindowContainerController appController =
+                new WindowTestUtils.TestAppWindowContainerController(taskController);
 
-        final TestTask task = (TestTask) taskController.mContainer;
+        final WindowTestUtils.TestTask task = (WindowTestUtils.TestTask) taskController.mContainer;
         final AppWindowToken app = appController.mContainer;
         task.mShouldDeferRemoval = true;
 
@@ -85,12 +80,12 @@
     public void testReparent() throws Exception {
         final StackWindowController stackController1 =
                 createStackControllerOnDisplay(sDisplayContent);
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController(stackController1);
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController1);
         final StackWindowController stackController2 =
                 createStackControllerOnDisplay(sDisplayContent);
-        final TestTaskWindowContainerController taskController2 =
-                new TestTaskWindowContainerController(stackController2);
+        final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+                new WindowTestUtils.TestTaskWindowContainerController(stackController2);
 
         boolean gotException = false;
         try {
@@ -114,8 +109,8 @@
 
         taskController.reparent(stackController2, 0);
         assertEquals(stackController2.mContainer, taskController.mContainer.getParent());
-        assertEquals(0, ((TestTask) taskController.mContainer).positionInParent());
-        assertEquals(1, ((TestTask) taskController2.mContainer).positionInParent());
+        assertEquals(0, ((WindowTestUtils.TestTask) taskController.mContainer).positionInParent());
+        assertEquals(1, ((WindowTestUtils.TestTask) taskController2.mContainer).positionInParent());
     }
 
     @Test
@@ -124,9 +119,9 @@
         final StackWindowController stack1Controller =
                 createStackControllerOnDisplay(sDisplayContent);
         final TaskStack stack1 = stack1Controller.mContainer;
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController(stack1Controller);
-        final TestTask task1 = (TestTask) taskController.mContainer;
+        final WindowTestUtils.TestTaskWindowContainerController taskController =
+                new WindowTestUtils.TestTaskWindowContainerController(stack1Controller);
+        final WindowTestUtils.TestTask task1 = (WindowTestUtils.TestTask) taskController.mContainer;
         task1.mOnDisplayChangedCalled = false;
         assertEquals(sDisplayContent, stack1.getDisplayContent());
 
@@ -134,9 +129,10 @@
         final DisplayContent dc = createNewDisplay();
         final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
         final TaskStack stack2 = stack2Controller.mContainer;
-        final TestTaskWindowContainerController taskController2 =
-                new TestTaskWindowContainerController(stack2Controller);
-        final TestTask task2 = (TestTask) taskController2.mContainer;
+        final WindowTestUtils.TestTaskWindowContainerController taskController2 =
+                new WindowTestUtils.TestTaskWindowContainerController(stack2Controller);
+        final WindowTestUtils.TestTask task2 =
+                (WindowTestUtils.TestTask) taskController2.mContainer;
 
         // Reparent and check state
         taskController.reparent(stack2Controller, 0);
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index cf8af67..0eaf5bc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -46,7 +46,7 @@
 
     @Test
     public void testFlow() throws Exception {
-        final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token);
         sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
         sWm.mUnknownAppVisibilityController.notifyRelayouted(token);
@@ -58,8 +58,8 @@
 
     @Test
     public void testMultiple() throws Exception {
-        final AppWindowToken token1 = new TestAppWindowToken(sDisplayContent);
-        final AppWindowToken token2 = new TestAppWindowToken(sDisplayContent);
+        final AppWindowToken token1 = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
+        final AppWindowToken token2 = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token1);
         sWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token2);
@@ -74,7 +74,7 @@
 
     @Test
     public void testClear() throws Exception {
-        final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token);
         sWm.mUnknownAppVisibilityController.clear();;
         assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
@@ -82,7 +82,7 @@
 
     @Test
     public void testAppRemoved() throws Exception {
-        final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token);
         sWm.mUnknownAppVisibilityController.appRemoved(token);
         assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 2e6eac0..a2aa058 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -102,7 +102,7 @@
         // Just any non zero value.
         sWm.mSystemDecorLayer = 10000;
 
-        mWindowToken = new TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
+        mWindowToken = new WindowTestUtils.TestAppWindowToken(sWm.getDefaultDisplayContentLocked());
         mStubStack = new TaskStack(sWm, 0);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
new file mode 100644
index 0000000..3a44357
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.IApplicationToken;
+import android.view.IWindow;
+import android.view.WindowManager;
+
+import static android.app.AppOpsManager.OP_NONE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.EMPTY;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static org.mockito.Mockito.mock;
+
+/**
+ * A collection of static functions that can be referenced by other test packages to provide access
+ * to WindowManager related test functionality.
+ */
+public class WindowTestUtils {
+    public static int sNextTaskId = 0;
+
+    /**
+     * Retrieves an instance of {@link WindowManagerService}, creating it if necessary.
+     */
+    public static WindowManagerService getWindowManagerService(Context context) {
+        return TestWindowManagerPolicy.getWindowManagerService(context);
+    }
+
+    /**
+     * Creates a mock instance of {@link StackWindowController}.
+     */
+    public static StackWindowController createMockStackWindowContainerController() {
+        StackWindowController controller = mock(StackWindowController.class);
+        controller.mContainer = mock(TestTaskStack.class);
+        return controller;
+    }
+
+    /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
+    public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
+            int userId) {
+        final Task newTask = new Task(WindowTestUtils.sNextTaskId++, stack, userId, service, null,
+                EMPTY, 0, false,
+                false, new ActivityManager.TaskDescription(), null);
+        stack.addTask(newTask, POSITION_TOP);
+        return newTask;
+    }
+
+    /**
+     * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
+     * normally be mocked out.
+     */
+    public static class TestTaskStack extends TaskStack {
+        TestTaskStack(WindowManagerService service, int stackId) {
+            super(service, stackId);
+        }
+
+        @Override
+        void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
+            // Do nothing.
+        }
+    }
+
+    /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
+    public static class TestAppWindowToken extends AppWindowToken {
+
+        TestAppWindowToken(DisplayContent dc) {
+            super(WindowTestsBase.sWm, null, false, dc, true /* fillsParent */,
+                    null /* overrideConfig */, null /* bounds */);
+        }
+
+        TestAppWindowToken(WindowManagerService service, IApplicationToken token,
+                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+                boolean alwaysFocusable, AppWindowContainerController controller,
+                Configuration overrideConfig, Rect bounds) {
+            super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
+                    showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
+                    launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
+        }
+
+        int getWindowsCount() {
+            return mChildren.size();
+        }
+
+        boolean hasWindow(WindowState w) {
+            return mChildren.contains(w);
+        }
+
+        WindowState getFirstChild() {
+            return mChildren.getFirst();
+        }
+
+        WindowState getLastChild() {
+            return mChildren.getLast();
+        }
+
+        int positionInParent() {
+            return getParent().mChildren.indexOf(this);
+        }
+    }
+
+    /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+    public static class TestWindowToken extends WindowToken {
+        int adj = 0;
+
+        TestWindowToken(int type, DisplayContent dc) {
+            this(type, dc, false /* persistOnEmpty */);
+        }
+
+        TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+            super(WindowTestsBase.sWm, mock(IBinder.class), type, persistOnEmpty, dc,
+                    false /* ownerCanManageAppTokens */);
+        }
+
+        int getWindowsCount() {
+            return mChildren.size();
+        }
+
+        boolean hasWindow(WindowState w) {
+            return mChildren.contains(w);
+        }
+
+        @Override
+        int getAnimLayerAdjustment() {
+            return adj;
+        }
+    }
+
+    /* Used so we can gain access to some protected members of the {@link Task} class */
+    public static class TestTask extends Task {
+        boolean mShouldDeferRemoval = false;
+        boolean mOnDisplayChangedCalled = false;
+        private boolean mUseLocalIsAnimating = false;
+        private boolean mIsAnimating = false;
+
+        TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
+                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+                boolean homeTask, TaskWindowContainerController controller) {
+            super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
+                    supportsPictureInPicture, homeTask, new ActivityManager.TaskDescription(),
+                    controller);
+        }
+
+        boolean shouldDeferRemoval() {
+            return mShouldDeferRemoval;
+        }
+
+        int positionInParent() {
+            return getParent().mChildren.indexOf(this);
+        }
+
+        @Override
+        void onDisplayChanged(DisplayContent dc) {
+            super.onDisplayChanged(dc);
+            mOnDisplayChangedCalled = true;
+        }
+
+        @Override
+        boolean isAnimating() {
+            return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
+        }
+
+        void setLocalIsAnimating(boolean isAnimating) {
+            mUseLocalIsAnimating = true;
+            mIsAnimating = isAnimating;
+        }
+    }
+
+    /**
+     * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
+     * class.
+     */
+    public static class TestTaskWindowContainerController extends TaskWindowContainerController {
+
+        TestTaskWindowContainerController() {
+            this(WindowTestsBase.createStackControllerOnDisplay(WindowTestsBase.sDisplayContent));
+        }
+
+        TestTaskWindowContainerController(StackWindowController stackController) {
+            super(sNextTaskId++, new TaskWindowContainerListener() {
+                        @Override
+                        public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+
+                        }
+
+                        @Override
+                        public void requestResize(Rect bounds, int resizeMode) {
+
+                        }
+                    }, stackController, 0 /* userId */, null /* bounds */,
+                    EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
+                    false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
+                    true /* showForAllUsers */, new ActivityManager.TaskDescription(), WindowTestsBase.sWm);
+        }
+
+        @Override
+        TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
+                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
+                boolean homeTask, ActivityManager.TaskDescription taskDescription) {
+            return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
+                    supportsPictureInPicture, homeTask, this);
+        }
+    }
+
+    public static class TestAppWindowContainerController extends AppWindowContainerController {
+
+        final IApplicationToken mToken;
+
+        TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
+            this(taskController, new TestIApplicationToken());
+        }
+
+        TestAppWindowContainerController(TestTaskWindowContainerController taskController,
+                IApplicationToken token) {
+            super(taskController, token, null /* listener */, 0 /* index */,
+                    SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
+                    true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
+                    false /* launchTaskBehind */, false /* alwaysFocusable */,
+                    0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
+                    0 /* inputDispatchingTimeoutNanos */, WindowTestsBase.sWm, null /* overrideConfig */,
+                    null /* bounds */);
+            mToken = token;
+        }
+
+        @Override
+        AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
+                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+                boolean alwaysFocusable, AppWindowContainerController controller,
+                Configuration overrideConfig, Rect bounds) {
+            return new TestAppWindowToken(service, token, voiceInteraction, dc,
+                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
+                    orientation,
+                    rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
+                    controller, overrideConfig, bounds);
+        }
+
+        AppWindowToken getAppWindowToken() {
+            return (AppWindowToken) WindowTestsBase.sDisplayContent.getWindowToken(mToken.asBinder());
+        }
+    }
+
+    public static class TestIApplicationToken implements IApplicationToken {
+
+        private final Binder mBinder = new Binder();
+        @Override
+        public IBinder asBinder() {
+            return mBinder;
+        }
+    }
+
+    /** Used to track resize reports. */
+    public static class TestWindowState extends WindowState {
+        boolean resizeReported;
+
+        TestWindowState(WindowManagerService service, Session session, IWindow window,
+                WindowManager.LayoutParams attrs, WindowToken token) {
+            super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
+                    false /* ownerCanAddInternalSystemWindow */);
+        }
+
+        @Override
+        void reportResized() {
+            super.reportResized();
+            resizeReported = true;
+        }
+
+        @Override
+        public boolean isGoneForLayoutLw() {
+            return false;
+        }
+
+        @Override
+        void updateResizingWindowIfNeeded() {
+            // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+            // the system that it can actually update the window.
+            boolean hadSurface = mHasSurface;
+            mHasSurface = true;
+
+            super.updateResizingWindowIfNeeded();
+
+            mHasSurface = hadSurface;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index a9d930f..eaf4ac4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -19,21 +19,16 @@
 import static android.view.View.VISIBLE;
 
 import android.app.ActivityManager.TaskDescription;
-import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManagerGlobal;
-import android.os.Binder;
 import android.view.Display;
 import android.view.DisplayInfo;
-import android.view.IApplicationToken;
 import org.junit.Assert;
 import org.junit.After;
 import org.junit.Before;
 import org.mockito.MockitoAnnotations;
 
-import android.app.ActivityManager.TaskSnapshot;
 import android.content.Context;
-import android.os.IBinder;
 import android.support.test.InstrumentationRegistry;
 import android.view.IWindow;
 import android.view.WindowManager;
@@ -41,10 +36,6 @@
 import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -58,7 +49,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
 import static org.mockito.Mockito.mock;
 
 import com.android.server.AttributeCache;
@@ -78,8 +68,7 @@
     // make sure we don't collide with any existing display. If we run into no other display, the
     // added display should be treated as default. This cannot be the default display
     private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
-    static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
-    private static int sNextTaskId = 0;
+    private static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
 
     private static boolean sOneTimeSetupDone = false;
     static DisplayContent sDisplayContent;
@@ -184,14 +173,14 @@
 
     private static WindowToken createWindowToken(DisplayContent dc, int stackId, int type) {
         if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
-            return new TestWindowToken(type, dc);
+            return new WindowTestUtils.TestWindowToken(type, dc);
         }
 
         final TaskStack stack = stackId == INVALID_STACK_ID
                 ? createTaskStackOnDisplay(dc)
                 : createStackControllerOnStackOnDisplay(stackId, dc).mContainer;
         final Task task = createTaskInStack(stack, 0 /* userId */);
-        final TestAppWindowToken token = new TestAppWindowToken(dc);
+        final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
         task.addChild(token, 0);
         return token;
     }
@@ -209,7 +198,7 @@
     }
 
     WindowState createAppWindow(Task task, int type, String name) {
-        final AppWindowToken token = new TestAppWindowToken(sDisplayContent);
+        final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(sDisplayContent);
         task.addChild(token, 0);
         return createWindow(null, type, token, name);
     }
@@ -260,10 +249,7 @@
 
     /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
     static Task createTaskInStack(TaskStack stack, int userId) {
-        final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, 0, false,
-                false, new TaskDescription(), null);
-        stack.addTask(newTask, POSITION_TOP);
-        return newTask;
+        return WindowTestUtils.createTaskInStack(sWm, stack, userId);
     }
 
     /** Creates a {@link DisplayContent} and adds it to the system. */
@@ -274,227 +260,10 @@
         return new DisplayContent(display, sWm, sLayersController, new WallpaperController(sWm));
     }
 
-    /* Used so we can gain access to some protected members of the {@link WindowToken} class */
-    static class TestWindowToken extends WindowToken {
-        int adj = 0;
-
-        TestWindowToken(int type, DisplayContent dc) {
-            this(type, dc, false /* persistOnEmpty */);
-        }
-
-        TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
-            super(sWm, mock(IBinder.class), type, persistOnEmpty, dc,
-                    false /* ownerCanManageAppTokens */);
-        }
-
-        int getWindowsCount() {
-            return mChildren.size();
-        }
-
-        boolean hasWindow(WindowState w) {
-            return mChildren.contains(w);
-        }
-
-        @Override
-        int getAnimLayerAdjustment() {
-            return adj;
-        }
+    /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
+    WindowTestUtils.TestWindowState createWindowState(WindowManager.LayoutParams attrs,
+            WindowToken token) {
+        return new WindowTestUtils.TestWindowState(sWm, sMockSession, sIWindow, attrs, token);
     }
 
-    /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
-    static class TestAppWindowToken extends AppWindowToken {
-
-        TestAppWindowToken(DisplayContent dc) {
-            super(sWm, null, false, dc, true /* fillsParent */, null /* overrideConfig */,
-                    null /* bounds */);
-        }
-
-        TestAppWindowToken(WindowManagerService service, IApplicationToken token,
-                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
-                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
-                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-                boolean alwaysFocusable, AppWindowContainerController controller,
-                Configuration overrideConfig, Rect bounds) {
-            super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
-                    showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
-                    launchTaskBehind, alwaysFocusable, controller, overrideConfig, bounds);
-        }
-
-        int getWindowsCount() {
-            return mChildren.size();
-        }
-
-        boolean hasWindow(WindowState w) {
-            return mChildren.contains(w);
-        }
-
-        WindowState getFirstChild() {
-            return mChildren.getFirst();
-        }
-
-        WindowState getLastChild() {
-            return mChildren.getLast();
-        }
-
-        int positionInParent() {
-            return getParent().mChildren.indexOf(this);
-        }
-    }
-
-    /* Used so we can gain access to some protected members of the {@link Task} class */
-    class TestTask extends Task {
-
-        boolean mShouldDeferRemoval = false;
-        boolean mOnDisplayChangedCalled = false;
-        private boolean mUseLocalIsAnimating = false;
-        private boolean mIsAnimating = false;
-
-        TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
-                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
-                boolean homeTask, TaskWindowContainerController controller) {
-            super(taskId, stack, userId, service, bounds, overrideConfig, resizeMode,
-                    supportsPictureInPicture, homeTask, new TaskDescription(), controller);
-        }
-
-        boolean shouldDeferRemoval() {
-            return mShouldDeferRemoval;
-        }
-
-        int positionInParent() {
-            return getParent().mChildren.indexOf(this);
-        }
-
-        @Override
-        void onDisplayChanged(DisplayContent dc) {
-            super.onDisplayChanged(dc);
-            mOnDisplayChangedCalled = true;
-        }
-
-        @Override
-        boolean isAnimating() {
-            return mUseLocalIsAnimating ? mIsAnimating : super.isAnimating();
-        }
-
-        void setLocalIsAnimating(boolean isAnimating) {
-            mUseLocalIsAnimating = true;
-            mIsAnimating = isAnimating;
-        }
-    }
-
-    /**
-     * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
-     * class.
-     */
-    class TestTaskWindowContainerController extends TaskWindowContainerController {
-
-        TestTaskWindowContainerController() {
-            this(createStackControllerOnDisplay(sDisplayContent));
-        }
-
-        TestTaskWindowContainerController(StackWindowController stackController) {
-            super(sNextTaskId++, new TaskWindowContainerListener() {
-                        @Override
-                        public void onSnapshotChanged(TaskSnapshot snapshot) {
-
-                        }
-
-                        @Override
-                        public void requestResize(Rect bounds, int resizeMode) {
-
-                        }
-                    }, stackController, 0 /* userId */, null /* bounds */,
-                    EMPTY /* overrideConfig*/, RESIZE_MODE_UNRESIZEABLE,
-                    false /* supportsPictureInPicture */, false /* homeTask*/, true /* toTop*/,
-                    true /* showForAllUsers */, new TaskDescription(), sWm);
-        }
-
-        @Override
-        TestTask createTask(int taskId, TaskStack stack, int userId, Rect bounds,
-                Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
-                boolean homeTask, TaskDescription taskDescription) {
-            return new TestTask(taskId, stack, userId, mService, bounds, overrideConfig, resizeMode,
-                    supportsPictureInPicture, homeTask, this);
-        }
-    }
-
-    class TestAppWindowContainerController extends AppWindowContainerController {
-
-        final IApplicationToken mToken;
-
-        TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
-            this(taskController, new TestIApplicationToken());
-        }
-
-        TestAppWindowContainerController(TestTaskWindowContainerController taskController,
-                IApplicationToken token) {
-            super(taskController, token, null /* listener */, 0 /* index */,
-                    SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
-                    true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
-                    false /* launchTaskBehind */, false /* alwaysFocusable */,
-                    0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
-                    0 /* inputDispatchingTimeoutNanos */, sWm, null /* overrideConfig */,
-                    null /* bounds */);
-            mToken = token;
-        }
-
-        @Override
-        AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
-                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
-                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
-                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-                boolean alwaysFocusable, AppWindowContainerController controller,
-                Configuration overrideConfig, Rect bounds) {
-            return new TestAppWindowToken(service, token, voiceInteraction, dc,
-                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
-                    orientation,
-                    rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
-                    controller, overrideConfig, bounds);
-        }
-
-        AppWindowToken getAppWindowToken() {
-            return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder());
-        }
-    }
-
-    class TestIApplicationToken implements IApplicationToken {
-
-        private final Binder mBinder = new Binder();
-        @Override
-        public IBinder asBinder() {
-            return mBinder;
-        }
-    }
-
-    /** Used to track resize reports. */
-    class TestWindowState extends WindowState {
-        boolean resizeReported;
-
-        TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
-            super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0,
-                    false /* ownerCanAddInternalSystemWindow */);
-        }
-
-        @Override
-        void reportResized() {
-            super.reportResized();
-            resizeReported = true;
-        }
-
-        @Override
-        public boolean isGoneForLayoutLw() {
-            return false;
-        }
-
-        @Override
-        void updateResizingWindowIfNeeded() {
-            // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
-            // the system that it can actually update the window.
-            boolean hadSurface = mHasSurface;
-            mHasSurface = true;
-
-            super.updateResizingWindowIfNeeded();
-
-            mHasSurface = hadSurface;
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index babb6d9..4f7ad41 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -46,7 +46,8 @@
 
     @Test
     public void testAddWindow() throws Exception {
-        final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
+        final WindowTestUtils.TestWindowToken token =
+                new WindowTestUtils.TestWindowToken(0, sDisplayContent);
 
         assertEquals(0, token.getWindowsCount());
 
@@ -76,7 +77,7 @@
     @Test
     public void testChildRemoval() throws Exception {
         final DisplayContent dc = sDisplayContent;
-        final TestWindowToken token = new TestWindowToken(0, dc);
+        final WindowTestUtils.TestWindowToken token = new WindowTestUtils.TestWindowToken(0, dc);
 
         assertEquals(token, dc.getWindowToken(token.token));
 
@@ -95,7 +96,8 @@
 
     @Test
     public void testAdjustAnimLayer() throws Exception {
-        final TestWindowToken token = new TestWindowToken(0, sDisplayContent);
+        final WindowTestUtils.TestWindowToken token =
+                new WindowTestUtils.TestWindowToken(0, sDisplayContent);
         final WindowState window1 = createWindow(null, TYPE_APPLICATION, token, "window1");
         final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
         final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
@@ -135,8 +137,9 @@
      */
     @Test
     public void testTokenRemovalProcess() throws Exception {
-        final TestWindowToken token =
-                new TestWindowToken(TYPE_TOAST, sDisplayContent, true /* persistOnEmpty */);
+        final WindowTestUtils.TestWindowToken token =
+                new WindowTestUtils.TestWindowToken(TYPE_TOAST, sDisplayContent,
+                        true /* persistOnEmpty */);
 
         // Verify that the token is on the display
         assertNotNull(sDisplayContent.getWindowToken(token.token));
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 7b8ebd4..01e36f5 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -1039,18 +1039,34 @@
      * Start the appropriate package when an device/accessory got attached.
      *
      * @param intent The intent to start the package
-     * @param matches The available resolutions of the intent
+     * @param rawMatches The available resolutions of the intent
      * @param defaultActivity The default activity for the device (if set)
      * @param device The device if a device was attached
      * @param accessory The accessory if a device was attached
      */
-    private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> matches,
+    private void resolveActivity(@NonNull Intent intent, @NonNull ArrayList<ResolveInfo> rawMatches,
             @Nullable ActivityInfo defaultActivity, @Nullable UsbDevice device,
             @Nullable UsbAccessory accessory) {
-        int count = matches.size();
+        final int numRawMatches = rawMatches.size();
+
+        // The raw matches contain the activities that can be started but also the intents to switch
+        // between the profiles
+        int numParentActivityMatches = 0;
+        int numNonParentActivityMatches = 0;
+        for (int i = 0; i < numRawMatches; i++) {
+            final ResolveInfo rawMatch = rawMatches.get(i);
+            if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+                if (UserHandle.getUserHandleForUid(
+                        rawMatch.activityInfo.applicationInfo.uid).equals(mParentUser)) {
+                    numParentActivityMatches++;
+                } else {
+                    numNonParentActivityMatches++;
+                }
+            }
+        }
 
         // don't show the resolver activity if there are no choices available
-        if (count == 0) {
+        if (numParentActivityMatches + numNonParentActivityMatches == 0) {
             if (accessory != null) {
                 String uri = accessory.getUri();
                 if (uri != null && uri.length() > 0) {
@@ -1073,6 +1089,21 @@
             return;
         }
 
+        // If only one profile has activity matches, we need to remove all switch intents
+        ArrayList<ResolveInfo> matches;
+        if (numParentActivityMatches == 0 || numNonParentActivityMatches == 0) {
+            matches = new ArrayList<>(numParentActivityMatches + numNonParentActivityMatches);
+
+            for (int i = 0; i < numRawMatches; i++) {
+                ResolveInfo rawMatch = rawMatches.get(i);
+                if (!rawMatch.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+                    matches.add(rawMatch);
+                }
+            }
+        } else {
+            matches = rawMatches;
+        }
+
         if (defaultActivity != null) {
             UsbUserSettingsManager defaultRIUserSettings = mSettingsManager.getSettingsForUser(
                     UserHandle.getUserId(defaultActivity.applicationInfo.uid));
@@ -1101,7 +1132,7 @@
             resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             UserHandle user;
 
-            if (count == 1) {
+            if (matches.size() == 1) {
                 ResolveInfo rInfo = matches.get(0);
 
                 // start UsbConfirmActivity if there is only one choice
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 92233b1..f80ee73 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -356,6 +356,7 @@
         private final StatusHints mStatusHints;
         private final Bundle mExtras;
         private final Bundle mIntentExtras;
+        private final long mCreationTimeMillis;
 
         /**
          * Whether the supplied capabilities  supports the specified capability.
@@ -578,9 +579,12 @@
         }
 
         /**
-         * @return The time the {@code Call} has been connected. This information is updated
-         * periodically, but user interfaces should not rely on this to display any "call time
-         * clock".
+         * Returns the time the {@link Call} connected (i.e. became active).  This information is
+         * updated periodically, but user interfaces should not rely on this to display the "call
+         * time clock".  For the time when the call was first added to Telecom, see
+         * {@link #getCreationTimeMillis()}.
+         *
+         * @return The time the {@link Call} connected in milliseconds since the epoch.
          */
         public final long getConnectTimeMillis() {
             return mConnectTimeMillis;
@@ -622,6 +626,18 @@
             return mIntentExtras;
         }
 
+        /**
+         * Returns the time when the call was first created and added to Telecom.  This is the same
+         * time that is logged as the start time in the Call Log (see
+         * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
+         * (became active), see {@link #getConnectTimeMillis()}.
+         *
+         * @return The creation time of the call, in millis since the epoch.
+         */
+        public long getCreationTimeMillis() {
+            return mCreationTimeMillis;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (o instanceof Details) {
@@ -641,28 +657,29 @@
                         Objects.equals(mVideoState, d.mVideoState) &&
                         Objects.equals(mStatusHints, d.mStatusHints) &&
                         areBundlesEqual(mExtras, d.mExtras) &&
-                        areBundlesEqual(mIntentExtras, d.mIntentExtras);
+                        areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
+                        Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
             }
             return false;
         }
 
         @Override
         public int hashCode() {
-            return
-                    Objects.hashCode(mHandle) +
-                    Objects.hashCode(mHandlePresentation) +
-                    Objects.hashCode(mCallerDisplayName) +
-                    Objects.hashCode(mCallerDisplayNamePresentation) +
-                    Objects.hashCode(mAccountHandle) +
-                    Objects.hashCode(mCallCapabilities) +
-                    Objects.hashCode(mCallProperties) +
-                    Objects.hashCode(mDisconnectCause) +
-                    Objects.hashCode(mConnectTimeMillis) +
-                    Objects.hashCode(mGatewayInfo) +
-                    Objects.hashCode(mVideoState) +
-                    Objects.hashCode(mStatusHints) +
-                    Objects.hashCode(mExtras) +
-                    Objects.hashCode(mIntentExtras);
+            return Objects.hash(mHandle,
+                            mHandlePresentation,
+                            mCallerDisplayName,
+                            mCallerDisplayNamePresentation,
+                            mAccountHandle,
+                            mCallCapabilities,
+                            mCallProperties,
+                            mDisconnectCause,
+                            mConnectTimeMillis,
+                            mGatewayInfo,
+                            mVideoState,
+                            mStatusHints,
+                            mExtras,
+                            mIntentExtras,
+                            mCreationTimeMillis);
         }
 
         /** {@hide} */
@@ -681,7 +698,8 @@
                 int videoState,
                 StatusHints statusHints,
                 Bundle extras,
-                Bundle intentExtras) {
+                Bundle intentExtras,
+                long creationTimeMillis) {
             mTelecomCallId = telecomCallId;
             mHandle = handle;
             mHandlePresentation = handlePresentation;
@@ -697,6 +715,7 @@
             mStatusHints = statusHints;
             mExtras = extras;
             mIntentExtras = intentExtras;
+            mCreationTimeMillis = creationTimeMillis;
         }
 
         /** {@hide} */
@@ -716,7 +735,8 @@
                     parcelableCall.getVideoState(),
                     parcelableCall.getStatusHints(),
                     parcelableCall.getExtras(),
-                    parcelableCall.getIntentExtras());
+                    parcelableCall.getIntentExtras(),
+                    parcelableCall.getCreationTimeMillis());
         }
 
         @Override
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 85a92d1..6212a77 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -59,6 +59,7 @@
     private final List<String> mConferenceableCallIds;
     private final Bundle mIntentExtras;
     private final Bundle mExtras;
+    private final long mCreationTimeMillis;
 
     public ParcelableCall(
             String id,
@@ -85,7 +86,8 @@
             int videoState,
             List<String> conferenceableCallIds,
             Bundle intentExtras,
-            Bundle extras) {
+            Bundle extras,
+            long creationTimeMillis) {
         mId = id;
         mState = state;
         mDisconnectCause = disconnectCause;
@@ -111,6 +113,7 @@
         mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds);
         mIntentExtras = intentExtras;
         mExtras = extras;
+        mCreationTimeMillis = creationTimeMillis;
     }
 
     /** The unique ID of the call. */
@@ -289,6 +292,13 @@
         return mIsVideoCallProviderChanged;
     }
 
+    /**
+     * @return The time the call was created, in milliseconds since the epoch.
+     */
+    public long getCreationTimeMillis() {
+        return mCreationTimeMillis;
+    }
+
     /** Responsible for creating ParcelableCall objects for deserialized Parcels. */
     public static final Parcelable.Creator<ParcelableCall> CREATOR =
             new Parcelable.Creator<ParcelableCall> () {
@@ -324,6 +334,7 @@
             int supportedAudioRoutes = source.readInt();
             boolean isRttCallChanged = source.readByte() == 1;
             ParcelableRttCall rttCall = source.readParcelable(classLoader);
+            long creationTimeMillis = source.readLong();
             return new ParcelableCall(
                     id,
                     state,
@@ -349,7 +360,8 @@
                     videoState,
                     conferenceableCallIds,
                     intentExtras,
-                    extras);
+                    extras,
+                    creationTimeMillis);
         }
 
         @Override
@@ -393,6 +405,7 @@
         destination.writeInt(mSupportedAudioRoutes);
         destination.writeByte((byte) (mIsRttCallChanged ? 1 : 0));
         destination.writeParcelable(mRttCall, 0);
+        destination.writeLong(mCreationTimeMillis);
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index b4c531e..f9875c5 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -53,8 +53,9 @@
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
+     * @deprecated use {@link Intent#ACTION_SERVICE_STATE}
      */
-    public static final String ACTION_SERVICE_STATE_CHANGED = "android.intent.action.SERVICE_STATE";
+    public static final String ACTION_SERVICE_STATE_CHANGED = Intent.ACTION_SERVICE_STATE;
 
     /**
      * <p>Broadcast Action: The radio technology has changed. The intent will have the following
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
index 36ebc90..71067ae 100644
--- a/tests/UiBench/Android.mk
+++ b/tests/UiBench/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := 24
+LOCAL_SDK_VERSION := current
 LOCAL_MIN_SDK_VERSION := 21
 
 # omit gradle 'build' dir
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
new file mode 100644
index 0000000..e4cbe93
--- /dev/null
+++ b/tests/WindowManagerStressTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2016 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := WindowManagerStressTest
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/WindowManagerStressTest/AndroidManifest.xml b/tests/WindowManagerStressTest/AndroidManifest.xml
new file mode 100644
index 0000000..17e0f15
--- /dev/null
+++ b/tests/WindowManagerStressTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.windowmanagerstresstest">
+
+    <application
+        android:allowBackup="false"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+        <activity android:name=".MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/WindowManagerStressTest/res/layout/activity_main.xml b/tests/WindowManagerStressTest/res/layout/activity_main.xml
new file mode 100644
index 0000000..6cf8269
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/layout/activity_main.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context="test.amslam.MainActivity">
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/run"
+        android:text="@string/run" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/output" />
+
+</LinearLayout>
diff --git a/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png b/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/WindowManagerStressTest/res/values/colors.xml b/tests/WindowManagerStressTest/res/values/colors.xml
new file mode 100644
index 0000000..4270ca6
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/dimens.xml b/tests/WindowManagerStressTest/res/values/dimens.xml
new file mode 100644
index 0000000..ed4ccbc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/dimens.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (C) 2016 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.
+-->
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/strings.xml b/tests/WindowManagerStressTest/res/values/strings.xml
new file mode 100644
index 0000000..cef05dc
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/strings.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources>
+    <string name="app_name">WmSlam</string>
+    <string name="run">Run</string>
+</resources>
diff --git a/tests/WindowManagerStressTest/res/values/styles.xml b/tests/WindowManagerStressTest/res/values/styles.xml
new file mode 100644
index 0000000..0983b25
--- /dev/null
+++ b/tests/WindowManagerStressTest/res/values/styles.xml
@@ -0,0 +1,23 @@
+<!-- Copyright (C) 2016 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.
+-->
+<resources>
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="android:colorPrimary">@color/colorPrimary</item>
+        <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="android:colorAccent">@color/colorAccent</item>
+    </style>
+</resources>
diff --git a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
new file mode 100644
index 0000000..6b9bb31
--- /dev/null
+++ b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package test.windowmanagerstresstest;
+
+import android.app.Activity;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.MergedConfiguration;
+import android.view.Display;
+import android.view.IWindowSession;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
+import android.widget.TextView;
+
+import com.android.internal.view.BaseIWindow;
+
+import java.util.ArrayList;
+
+public class MainActivity extends Activity {
+
+    private static final String TAG = "WmSlam";
+
+    private TextView mOutput;
+    private volatile boolean finished;
+    private final ArrayList<BaseIWindow> mWindows = new ArrayList<>();
+    private final LayoutParams mLayoutParams = new LayoutParams();
+    private final Rect mTmpRect = new Rect();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        mOutput = (TextView) findViewById(R.id.output);
+
+        findViewById(R.id.run).setOnClickListener(view -> {
+            view.setEnabled(false);
+            mOutput.setText("");
+            startBatch();
+        });
+        mLayoutParams.token = getActivityToken();
+    }
+
+    void startBatch() {
+        new Thread(() -> {
+            finished = false;
+            addWindows();
+            startCpuRunnables();
+            for (int i = 0; i < 5; i++) {
+                final long time = SystemClock.uptimeMillis();
+                slamWm();
+                log("Total: " + (SystemClock.uptimeMillis() - time) + " ms");
+            }
+            removeWindows();
+            finished = true;
+        }).start();
+    }
+
+    void startCpuRunnables() {
+        for (int i = 0; i < 10; i++) {
+            new Thread(mUseCpuRunnable).start();
+        }
+    }
+
+    private final Runnable mUseCpuRunnable = new Runnable() {
+        @Override
+        public void run() {
+            while (!finished) {
+            }
+        }
+    };
+
+    private void log(String text) {
+        mOutput.post(() -> mOutput.append(text + "\n"));
+        Log.d(TAG, text);
+    }
+
+    private void slamWm() {
+        ArrayList<Thread> threads = new ArrayList<>();
+        for (int i = 0; i < 20; i++) {
+            for (BaseIWindow window : mWindows) {
+                Thread t = new Thread(() -> {
+                    try {
+                        WindowManagerGlobal.getWindowSession().relayout(window,
+                                window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, mTmpRect,
+                                mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
+                                new MergedConfiguration(), new Surface());
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
+                    }
+                });
+                threads.add(t);
+                t.start();
+            }
+        }
+        for (Thread t : threads) {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    void addWindows() {
+        for (int i = 0; i < 50; i++) {
+            final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+            layoutParams.token = getActivityToken();
+            final BaseIWindow window = new BaseIWindow();
+            final IWindowSession session = WindowManagerGlobal.getWindowSession();
+            final Rect tmpRect = new Rect();
+            try {
+                final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq, layoutParams,
+                        View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect);
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+            mWindows.add(window);
+        }
+    }
+
+    void removeWindows() {
+        for (BaseIWindow window : mWindows) {
+            try {
+                WindowManagerGlobal.getWindowSession().remove(window);
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 04443a5..c562cb9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -80,6 +80,7 @@
 import com.android.server.connectivity.NetworkMonitor;
 import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
 import com.android.server.net.NetworkPinner;
+import com.android.server.net.NetworkPolicyManagerInternal;
 
 import java.net.InetAddress;
 import java.util.ArrayList;
@@ -713,6 +714,9 @@
         }
 
         mServiceContext = new MockContext(getContext());
+        LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
+        LocalServices.addService(
+                NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
         mService = new WrappedConnectivityService(mServiceContext,
                 mock(INetworkManagementService.class),
                 mock(INetworkStatsService.class),
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 7f71589..a33fd06 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -1913,7 +1913,7 @@
   std::vector<std::string> overlay_arg_list;
   std::vector<std::string> extra_java_packages;
   Maybe<std::string> package_id;
-  Maybe<std::string> configs;
+  std::vector<std::string> configs;
   Maybe<std::string> preferred_density;
   Maybe<std::string> product_list;
   bool legacy_x_flag = false;
@@ -1971,7 +1971,7 @@
                           &legacy_x_flag)
           .OptionalSwitch("-z", "Require localization of strings marked 'suggested'",
                           &require_localization)
-          .OptionalFlag("-c",
+          .OptionalFlagList("-c",
                         "Comma separated list of configurations to include. The default\n"
                         "is all configurations",
                         &configs)
@@ -2151,28 +2151,29 @@
   }
 
   AxisConfigFilter filter;
-  if (configs) {
-    for (const StringPiece& config_str : util::Tokenize(configs.value(), ',')) {
-      ConfigDescription config;
-      LocaleValue lv;
-      if (lv.InitFromFilterString(config_str)) {
-        lv.WriteTo(&config);
-      } else if (!ConfigDescription::Parse(config_str, &config)) {
-        context.GetDiagnostics()->Error(DiagMessage() << "invalid config '"
-                                                      << config_str
-                                                      << "' for -c option");
-        return 1;
-      }
+  if (configs.empty()) {
+    for (const std::string& config_arg : configs) {
+      for (const StringPiece& config_str : util::Tokenize(config_arg, ',')) {
+        ConfigDescription config;
+        LocaleValue lv;
+        if (lv.InitFromFilterString(config_str)) {
+          lv.WriteTo(&config);
+        } else if (!ConfigDescription::Parse(config_str, &config)) {
+          context.GetDiagnostics()->Error(DiagMessage() << "invalid config '"
+                                                        << config_str
+                                                        << "' for -c option");
+          return 1;
+        }
 
-      if (config.density != 0) {
-        context.GetDiagnostics()->Warn(DiagMessage() << "ignoring density '"
-                                                     << config
-                                                     << "' for -c option");
-      } else {
-        filter.AddConfig(config);
+        if (config.density != 0) {
+          context.GetDiagnostics()->Warn(DiagMessage() << "ignoring density '"
+                                                       << config
+                                                       << "' for -c option");
+        } else {
+          filter.AddConfig(config);
+        }
       }
     }
-
     options.table_splitter_options.config_filter = &filter;
   }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index 7fe464a..a21fe68 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -26,6 +26,7 @@
 import android.annotation.Nullable;
 import android.content.res.AssetManager;
 import android.content.res.BridgeAssetManager;
+import android.graphics.fonts.FontVariationAxis;
 import android.text.FontConfig;
 
 import java.awt.Font;
@@ -250,7 +251,7 @@
     // ---- delegate methods ----
     @LayoutlibDelegate
     /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex,
-            FontConfig.Axis[] axes, int weight, int italic) {
+            FontVariationAxis[] axes, int weight, int italic) {
         if (thisFontFamily.mBuilderPtr == 0) {
             assert false : "Unable to call addFont after freezing.";
             return false;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 80e3bad..c7818a3 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.graphics.FontFamily_Delegate.FontVariant;
+import android.graphics.fonts.FontVariationAxis;
 import android.text.FontConfig;
 
 import java.awt.Font;
@@ -163,7 +164,7 @@
 
     @LayoutlibDelegate
     /*package*/ static synchronized long nativeCreateFromTypefaceWithVariation(long native_instance,
-            List<FontConfig.Axis> axes) {
+            List<FontVariationAxis> axes) {
         long newInstance = nativeCreateFromTypeface(native_instance, 0);
 
         if (newInstance != 0) {