Merge "Don't back up disabled apps" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 59367ee..0cc4361 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -211,6 +211,7 @@
     ctor public R.attr();
     field public static final int __removed1 = 16844099; // 0x1010543
     field public static final int __removed2 = 16844104; // 0x1010548
+    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -313,7 +314,6 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofillMode = 16844116; // 0x1010554
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -3615,6 +3615,7 @@
     method public android.net.Uri getReferrer();
     method public int getRequestedOrientation();
     method public final android.view.SearchEvent getSearchEvent();
+    method public long getStartInitiatedTime();
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
@@ -6091,6 +6092,17 @@
     method public void onDetached();
   }
 
+  public final class WallpaperColors implements android.os.Parcelable {
+    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+    method public int describeContents();
+    method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+    method public boolean supportsDarkText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6113,6 +6125,8 @@
   }
 
   public class WallpaperManager {
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
     method public void clear() throws java.io.IOException;
     method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6127,6 +6141,7 @@
     method public android.graphics.drawable.Drawable getDrawable();
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperColors getWallpaperColors(int);
     method public android.os.ParcelFileDescriptor getWallpaperFile(int);
     method public int getWallpaperId(int);
     method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6135,6 +6150,7 @@
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
     method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6159,6 +6175,10 @@
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
+  public static abstract interface WallpaperManager.OnColorsChangedListener {
+    method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+  }
+
 }
 
 package android.app.admin {
@@ -6869,6 +6889,14 @@
     field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
+  public abstract class JobServiceEngine {
+    ctor public JobServiceEngine(android.content.Context);
+    method public final android.os.IBinder getBinder();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+  }
+
   public final class JobWorkItem implements android.os.Parcelable {
     ctor public JobWorkItem(android.content.Intent);
     ctor public JobWorkItem(android.os.Parcel);
@@ -8069,7 +8097,12 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
     method public void stopScan(android.bluetooth.le.ScanCallback);
+    method public void stopScan(android.app.PendingIntent);
+    field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+    field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+    field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
   }
 
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8253,6 +8286,8 @@
     method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
     method public void disassociate(java.lang.String);
     method public java.util.List<java.lang.String> getAssociations();
+    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method public void requestNotificationAccess(android.content.ComponentName);
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -9325,7 +9360,6 @@
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
-    field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
     field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
     field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -21872,7 +21906,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -21970,6 +22004,19 @@
     method public void set(int, int);
   }
 
+  public static final class MediaCodec.MetricsConstants {
+    field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+    field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+    field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
@@ -22425,7 +22472,7 @@
     method public long getCachedDuration();
     method public android.media.MediaExtractor.CasInfo getCasInfo(int);
     method public android.media.DrmInitData getDrmInitData();
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -22460,6 +22507,12 @@
     method public int getSystemId();
   }
 
+  public static final class MediaExtractor.MetricsConstants {
+    field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+    field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
   public final class MediaFormat {
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
@@ -22685,69 +22738,6 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public final class MediaMetricsSet {
-    method public double getDouble(java.lang.String, double);
-    method public int getInt(java.lang.String, int);
-    method public long getLong(java.lang.String, long);
-    method public java.lang.String getString(java.lang.String, java.lang.String);
-    method public boolean isEmpty();
-    method public java.util.Set<java.lang.String> keySet();
-    method public int size();
-  }
-
-  public static final class MediaMetricsSet.MediaCodec {
-    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
-    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
-    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
-    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
-    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
-    field public static final java.lang.String MODE_AUDIO = "audio";
-    field public static final java.lang.String MODE_VIDEO = "video";
-  }
-
-  public static final class MediaMetricsSet.MediaExtractor {
-    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
-    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
-    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-  }
-
-  public static final class MediaMetricsSet.MediaPlayer {
-    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static final class MediaMetricsSet.MediaRecorder {
-    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
-    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
-    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
-  }
-
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22786,7 +22776,7 @@
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22881,6 +22871,21 @@
     method public java.util.UUID[] getSupportedSchemes();
   }
 
+  public static final class MediaPlayer.MetricsConstants {
+    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+  }
+
   public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
     ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
   }
@@ -22955,7 +22960,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -22974,11 +22979,12 @@
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
-    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
     method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.io.File);
     method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
     method public void setOutputFormat(int) throws java.lang.IllegalStateException;
     method public void setPreviewDisplay(android.view.Surface);
@@ -23023,6 +23029,25 @@
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
 
+  public static final class MediaRecorder.MetricsConstants {
+    field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+  }
+
   public static abstract interface MediaRecorder.OnErrorListener {
     method public abstract void onError(android.media.MediaRecorder, int, int);
   }
@@ -25782,6 +25807,10 @@
     method public android.net.NetworkRequest.Builder removeCapability(int);
     method public android.net.NetworkRequest.Builder removeTransportType(int);
     method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
+    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
+  }
+
+  public abstract class NetworkSpecifier {
   }
 
   public class ParseException extends java.lang.RuntimeException {
@@ -37035,8 +37064,10 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
-    method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+    method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+    method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
@@ -37061,6 +37092,25 @@
     method public void onSuccess(android.service.autofill.FillResponse);
   }
 
+  public final class FillContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRequestId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+  }
+
+  public final class FillRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public int getFlags();
+    method public int getId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+  }
+
   public final class FillResponse implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -37072,7 +37122,8 @@
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
     method public android.service.autofill.FillResponse build();
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
-    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+    method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -37101,6 +37152,14 @@
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
   }
 
+  public final class SaveRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+  }
+
 }
 
 package android.service.carrier {
@@ -37734,10 +37793,12 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public void invalidateColors();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public android.app.WallpaperColors onComputeWallpaperColors();
     method public void onCreate(android.view.SurfaceHolder);
     method public void onDesiredSizeChanged(int, int);
     method public void onDestroy();
@@ -45368,7 +45429,6 @@
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
     method public java.lang.String[] getAutofillHints();
-    method public int getAutofillMode();
     method public int getAutofillType();
     method public android.view.autofill.AutofillValue getAutofillValue();
     method public android.graphics.drawable.Drawable getBackground();
@@ -45457,7 +45517,6 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
-    method public int getResolvedAutofillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -45690,7 +45749,6 @@
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAutofillHints(java.lang.String...);
-    method public void setAutofillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
     method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -45846,9 +45904,6 @@
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
     field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
-    field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
-    field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
-    field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
     field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
     field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -46416,7 +46471,6 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
-    method public default int getResolvedAutofillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -47803,7 +47857,7 @@
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
-    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+    field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
   public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/removed.txt b/api/removed.txt
index 82705fd..1e8370e 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -5,10 +5,6 @@
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
   }
 
-  public static class Notification.Builder {
-    method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
-  }
-
   public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
     method public deprecated void showAsNotification(android.content.Context);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index fd176d0..21fce31 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -329,6 +329,7 @@
     ctor public R.attr();
     field public static final int __removed1 = 16844099; // 0x1010543
     field public static final int __removed2 = 16844104; // 0x1010548
+    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -431,7 +432,6 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofillMode = 16844116; // 0x1010554
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -3743,6 +3743,7 @@
     method public android.net.Uri getReferrer();
     method public int getRequestedOrientation();
     method public final android.view.SearchEvent getSearchEvent();
+    method public long getStartInitiatedTime();
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
@@ -6295,6 +6296,17 @@
     method public void setPersistentVrModeEnabled(boolean);
   }
 
+  public final class WallpaperColors implements android.os.Parcelable {
+    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+    method public int describeContents();
+    method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+    method public boolean supportsDarkText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6317,6 +6329,8 @@
   }
 
   public class WallpaperManager {
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
     method public void clear() throws java.io.IOException;
     method public void clear(int) throws java.io.IOException;
     method public void clearWallpaper();
@@ -6333,6 +6347,7 @@
     method public android.graphics.drawable.Drawable getDrawable();
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperColors getWallpaperColors(int);
     method public android.os.ParcelFileDescriptor getWallpaperFile(int);
     method public int getWallpaperId(int);
     method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6341,6 +6356,7 @@
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
     method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6368,6 +6384,10 @@
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
+  public static abstract interface WallpaperManager.OnColorsChangedListener {
+    method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+  }
+
 }
 
 package android.app.admin {
@@ -7303,6 +7323,14 @@
     field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
+  public abstract class JobServiceEngine {
+    ctor public JobServiceEngine(android.content.Context);
+    method public final android.os.IBinder getBinder();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+  }
+
   public final class JobWorkItem implements android.os.Parcelable {
     ctor public JobWorkItem(android.content.Intent);
     ctor public JobWorkItem(android.os.Parcel);
@@ -8541,10 +8569,15 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
     method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
     method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
     method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
     method public void stopScan(android.bluetooth.le.ScanCallback);
+    method public void stopScan(android.app.PendingIntent);
+    field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+    field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+    field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
   }
 
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8747,6 +8780,8 @@
     method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
     method public void disassociate(java.lang.String);
     method public java.util.List<java.lang.String> getAssociations();
+    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method public void requestNotificationAccess(android.content.ComponentName);
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -11239,6 +11274,7 @@
     method public abstract byte[] getInstantAppCookie();
     method public abstract int getInstantAppCookieMaxSize();
     method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+    method public abstract android.content.ComponentName getInstantAppInstallerComponent();
     method public abstract android.content.ComponentName getInstantAppResolverSettingsComponent();
     method public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -23704,7 +23740,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -23802,6 +23838,19 @@
     method public void set(int, int);
   }
 
+  public static final class MediaCodec.MetricsConstants {
+    field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+    field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+    field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
@@ -24257,7 +24306,7 @@
     method public long getCachedDuration();
     method public android.media.MediaExtractor.CasInfo getCasInfo(int);
     method public android.media.DrmInitData getDrmInitData();
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -24292,6 +24341,12 @@
     method public int getSystemId();
   }
 
+  public static final class MediaExtractor.MetricsConstants {
+    field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+    field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
   public final class MediaFormat {
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
@@ -24517,69 +24572,6 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public final class MediaMetricsSet {
-    method public double getDouble(java.lang.String, double);
-    method public int getInt(java.lang.String, int);
-    method public long getLong(java.lang.String, long);
-    method public java.lang.String getString(java.lang.String, java.lang.String);
-    method public boolean isEmpty();
-    method public java.util.Set<java.lang.String> keySet();
-    method public int size();
-  }
-
-  public static final class MediaMetricsSet.MediaCodec {
-    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
-    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
-    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
-    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
-    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
-    field public static final java.lang.String MODE_AUDIO = "audio";
-    field public static final java.lang.String MODE_VIDEO = "video";
-  }
-
-  public static final class MediaMetricsSet.MediaExtractor {
-    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
-    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
-    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-  }
-
-  public static final class MediaMetricsSet.MediaPlayer {
-    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static final class MediaMetricsSet.MediaRecorder {
-    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
-    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
-    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
-  }
-
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -24618,7 +24610,7 @@
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -24713,6 +24705,21 @@
     method public java.util.UUID[] getSupportedSchemes();
   }
 
+  public static final class MediaPlayer.MetricsConstants {
+    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+  }
+
   public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
     ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
   }
@@ -24787,7 +24794,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -24806,11 +24813,12 @@
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
-    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
     method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.io.File);
     method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
     method public void setOutputFormat(int) throws java.lang.IllegalStateException;
     method public void setPreviewDisplay(android.view.Surface);
@@ -24857,6 +24865,25 @@
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
 
+  public static final class MediaRecorder.MetricsConstants {
+    field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+  }
+
   public static abstract interface MediaRecorder.OnErrorListener {
     method public abstract void onError(android.media.MediaRecorder, int, int);
   }
@@ -28004,6 +28031,7 @@
     method public android.net.NetworkRequest.Builder removeCapability(int);
     method public android.net.NetworkRequest.Builder removeTransportType(int);
     method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
+    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
   }
 
   public class NetworkScoreManager {
@@ -28022,6 +28050,9 @@
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "packageName";
   }
 
+  public abstract class NetworkSpecifier {
+  }
+
   public class ParseException extends java.lang.RuntimeException {
     field public java.lang.String response;
   }
@@ -28144,10 +28175,6 @@
     field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
     field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
     field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
-    field public static final deprecated int BADGING_4K = 30; // 0x1e
-    field public static final deprecated int BADGING_HD = 20; // 0x14
-    field public static final deprecated int BADGING_NONE = 0; // 0x0
-    field public static final deprecated int BADGING_SD = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
     field public final android.os.Bundle attributes;
     field public final boolean meteredHint;
@@ -28155,9 +28182,6 @@
     field public final android.net.RssiCurve rssiCurve;
   }
 
-  public static abstract deprecated class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
-  }
-
   public class TrafficStats {
     ctor public TrafficStats();
     method public static void clearThreadStatsTag();
@@ -40151,8 +40175,10 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
-    method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+    method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+    method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
@@ -40177,6 +40203,25 @@
     method public void onSuccess(android.service.autofill.FillResponse);
   }
 
+  public final class FillContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRequestId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+  }
+
+  public final class FillRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public int getFlags();
+    method public int getId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+  }
+
   public final class FillResponse implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -40188,7 +40233,8 @@
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
     method public android.service.autofill.FillResponse build();
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
-    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+    method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -40217,6 +40263,14 @@
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
   }
 
+  public final class SaveRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+  }
+
 }
 
 package android.service.carrier {
@@ -40992,10 +41046,12 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public void invalidateColors();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public android.app.WallpaperColors onComputeWallpaperColors();
     method public void onCreate(android.view.SurfaceHolder);
     method public void onDesiredSizeChanged(int, int);
     method public void onDestroy();
@@ -44520,6 +44576,7 @@
     method public byte[] getInstantAppCookie();
     method public int getInstantAppCookieMaxSize();
     method public android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+    method public android.content.ComponentName getInstantAppInstallerComponent();
     method public android.content.ComponentName getInstantAppResolverSettingsComponent();
     method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -48948,7 +49005,6 @@
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
     method public java.lang.String[] getAutofillHints();
-    method public int getAutofillMode();
     method public int getAutofillType();
     method public android.view.autofill.AutofillValue getAutofillValue();
     method public android.graphics.drawable.Drawable getBackground();
@@ -49037,7 +49093,6 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
-    method public int getResolvedAutofillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -49270,7 +49325,6 @@
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAutofillHints(java.lang.String...);
-    method public void setAutofillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
     method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -49426,9 +49480,6 @@
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
     field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
-    field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
-    field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
-    field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
     field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
     field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -49996,7 +50047,6 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
-    method public default int getResolvedAutofillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -51386,7 +51436,7 @@
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
-    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+    field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
   public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index bdcafae..7bdb957 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -5,10 +5,6 @@
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
   }
 
-  public static class Notification.Builder {
-    method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
-  }
-
   public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
     method public deprecated void showAsNotification(android.content.Context);
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 1504b29..18f86b8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -211,6 +211,7 @@
     ctor public R.attr();
     field public static final int __removed1 = 16844099; // 0x1010543
     field public static final int __removed2 = 16844104; // 0x1010548
+    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -313,7 +314,6 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofillMode = 16844116; // 0x1010554
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -3617,6 +3617,7 @@
     method public android.net.Uri getReferrer();
     method public int getRequestedOrientation();
     method public final android.view.SearchEvent getSearchEvent();
+    method public long getStartInitiatedTime();
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
@@ -6111,6 +6112,17 @@
     method public void onDetached();
   }
 
+  public final class WallpaperColors implements android.os.Parcelable {
+    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+    method public int describeContents();
+    method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+    method public boolean supportsDarkText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6133,6 +6145,8 @@
   }
 
   public class WallpaperManager {
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
     method public void clear() throws java.io.IOException;
     method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6147,6 +6161,7 @@
     method public android.graphics.drawable.Drawable getDrawable();
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperColors getWallpaperColors(int);
     method public android.os.ParcelFileDescriptor getWallpaperFile(int);
     method public int getWallpaperId(int);
     method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6155,6 +6170,7 @@
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
     method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6179,6 +6195,10 @@
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
+  public static abstract interface WallpaperManager.OnColorsChangedListener {
+    method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+  }
+
 }
 
 package android.app.admin {
@@ -6899,6 +6919,14 @@
     field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
+  public abstract class JobServiceEngine {
+    ctor public JobServiceEngine(android.content.Context);
+    method public final android.os.IBinder getBinder();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+  }
+
   public final class JobWorkItem implements android.os.Parcelable {
     ctor public JobWorkItem(android.content.Intent);
     ctor public JobWorkItem(android.os.Parcel);
@@ -8100,7 +8128,12 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
     method public void stopScan(android.bluetooth.le.ScanCallback);
+    method public void stopScan(android.app.PendingIntent);
+    field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+    field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+    field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
   }
 
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8284,6 +8317,8 @@
     method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
     method public void disassociate(java.lang.String);
     method public java.util.List<java.lang.String> getAssociations();
+    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method public void requestNotificationAccess(android.content.ComponentName);
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -9359,7 +9394,6 @@
     field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
     field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
-    field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
     field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
     field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -21979,7 +22013,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22077,6 +22111,19 @@
     method public void set(int, int);
   }
 
+  public static final class MediaCodec.MetricsConstants {
+    field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+    field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+    field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
@@ -22532,7 +22579,7 @@
     method public long getCachedDuration();
     method public android.media.MediaExtractor.CasInfo getCasInfo(int);
     method public android.media.DrmInitData getDrmInitData();
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -22567,6 +22614,12 @@
     method public int getSystemId();
   }
 
+  public static final class MediaExtractor.MetricsConstants {
+    field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+    field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
   public final class MediaFormat {
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
@@ -22792,69 +22845,6 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public final class MediaMetricsSet {
-    method public double getDouble(java.lang.String, double);
-    method public int getInt(java.lang.String, int);
-    method public long getLong(java.lang.String, long);
-    method public java.lang.String getString(java.lang.String, java.lang.String);
-    method public boolean isEmpty();
-    method public java.util.Set<java.lang.String> keySet();
-    method public int size();
-  }
-
-  public static final class MediaMetricsSet.MediaCodec {
-    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
-    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
-    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
-    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
-    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
-    field public static final java.lang.String MODE_AUDIO = "audio";
-    field public static final java.lang.String MODE_VIDEO = "video";
-  }
-
-  public static final class MediaMetricsSet.MediaExtractor {
-    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
-    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
-    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-  }
-
-  public static final class MediaMetricsSet.MediaPlayer {
-    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static final class MediaMetricsSet.MediaRecorder {
-    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
-    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
-    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
-  }
-
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22893,7 +22883,7 @@
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
     method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22988,6 +22978,21 @@
     method public java.util.UUID[] getSupportedSchemes();
   }
 
+  public static final class MediaPlayer.MetricsConstants {
+    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+  }
+
   public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
     ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
   }
@@ -23062,7 +23067,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -23081,11 +23086,12 @@
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
-    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
     method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.io.File);
     method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
     method public void setOutputFormat(int) throws java.lang.IllegalStateException;
     method public void setPreviewDisplay(android.view.Surface);
@@ -23130,6 +23136,25 @@
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
 
+  public static final class MediaRecorder.MetricsConstants {
+    field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+  }
+
   public static abstract interface MediaRecorder.OnErrorListener {
     method public abstract void onError(android.media.MediaRecorder, int, int);
   }
@@ -25889,6 +25914,10 @@
     method public android.net.NetworkRequest.Builder removeCapability(int);
     method public android.net.NetworkRequest.Builder removeTransportType(int);
     method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String);
+    method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
+  }
+
+  public abstract class NetworkSpecifier {
   }
 
   public class ParseException extends java.lang.RuntimeException {
@@ -37188,8 +37217,10 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
-    method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+    method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+    method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
@@ -37214,6 +37245,25 @@
     method public void onSuccess(android.service.autofill.FillResponse);
   }
 
+  public final class FillContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRequestId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+  }
+
+  public final class FillRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public int getFlags();
+    method public int getId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+  }
+
   public final class FillResponse implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -37225,7 +37275,8 @@
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
     method public android.service.autofill.FillResponse build();
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
-    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+    method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -37254,6 +37305,14 @@
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
   }
 
+  public final class SaveRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+  }
+
 }
 
 package android.service.carrier {
@@ -37928,10 +37987,12 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public void invalidateColors();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public android.app.WallpaperColors onComputeWallpaperColors();
     method public void onCreate(android.view.SurfaceHolder);
     method public void onDesiredSizeChanged(int, int);
     method public void onDestroy();
@@ -45734,7 +45795,6 @@
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
     method public java.lang.String[] getAutofillHints();
-    method public int getAutofillMode();
     method public int getAutofillType();
     method public android.view.autofill.AutofillValue getAutofillValue();
     method public android.graphics.drawable.Drawable getBackground();
@@ -45823,7 +45883,6 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
-    method public int getResolvedAutofillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -46059,7 +46118,6 @@
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAutofillHints(java.lang.String...);
-    method public void setAutofillMode(int);
     method public void setAutofilled(boolean);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
@@ -46216,9 +46274,6 @@
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
     field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
-    field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
-    field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
-    field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
     field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
     field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -46790,7 +46845,6 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
-    method public default int getResolvedAutofillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -48181,7 +48235,7 @@
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
-    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+    field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
   public static abstract class AutofillManager.AutofillCallback {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 82705fd..1e8370e 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -5,10 +5,6 @@
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
   }
 
-  public static class Notification.Builder {
-    method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
-  }
-
   public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
     method public deprecated void showAsNotification(android.content.Context);
   }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 950991b..b36a160 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,6 +18,7 @@
 
 import android.metrics.LogMaker;
 import android.graphics.Rect;
+import android.os.SystemClock;
 import android.view.ViewRootImpl.ActivityConfigCallback;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
@@ -7433,6 +7434,25 @@
         }
     }
 
+    /**
+     * Return the timestamp at which this activity start was last initiated by the system in the
+     * {@link SystemClock#uptimeMillis()} time base.
+     *
+     * This can be used to understand how much time is taken for an activity to be started and
+     * displayed to the user.
+     *
+     * @return timestamp at which this activity start was initiated by the system
+     *         or {@code 0} if for any reason the timestamp could not be retrieved.
+     */
+    public long getStartInitiatedTime() {
+        try {
+            return ActivityManager.getService().getActivityStartInitiatedTime(mToken);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to call getActivityStartTime", e);
+            return 0;
+        }
+    }
+
     class HostCallbacks extends FragmentHostCallback<Activity> {
         public HostCallbacks() {
             super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a6838f8b..e07b7e4 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2639,4 +2639,13 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        try {
+            return mPM.getInstantAppInstallerComponent();
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index fc827a9..4210d2e 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -632,6 +632,8 @@
      */
      void backgroundWhitelistUid(int uid);
 
+     long getActivityStartInitiatedTime(IBinder token);
+
     // WARNING: when these transactions are updated, check if they are any callers on the native
     // side. If so, make sure they are using the correct transaction ids and arguments.
     // If a transaction which will also be used on the native side is being inserted, add it
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7f26f4f..ed316bd 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2339,7 +2339,9 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Notification(pri=");
+        sb.append("Notification(channel=");
+        sb.append(getChannel());
+        sb.append(" pri=");
         sb.append(priority);
         sb.append(" contentView=");
         if (contentView != null) {
@@ -2729,21 +2731,6 @@
         }
 
         /**
-         * @removed
-         * Sets which icon to display as a badge for this notification.
-         *
-         * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
-         * {@link #BADGE_ICON_LARGE}.
-         *
-         * Note: This value might be ignored, for launchers that don't support badge icons.
-         */
-        @Deprecated
-        public Builder chooseBadgeIcon(int icon) {
-            mN.mBadgeIcon = icon;
-            return this;
-        }
-
-        /**
          * Sets which icon to display as a badge for this notification.
          *
          * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3191eec..6f326de 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -112,13 +112,6 @@
     private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>>
             mAdjustedDisplays = new ArrayMap<>();
 
-    /**
-     * A cache of DisplayId, Resources to Display. These display adjustments associated with these
-     * {@link Display}s will change as the resources change.
-     */
-    private final ArrayMap<Pair<Integer, ResourcesKey>, WeakReference<Display>> mResourceDisplays =
-        new ArrayMap<>();
-
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
             if (sResourcesManager == null) {
@@ -251,51 +244,16 @@
      */
     public Display getAdjustedDisplay(final int displayId, Resources resources) {
         synchronized (this) {
-            // Note that the ResourcesKey might be {@code null} in the case that the
-            // {@link Resources} is actually from {@link Resources#getSystem}. In this case, it is
-            // not managed by {@link ResourcesManager}, but we still want to cache the display
-            // object.
-            final Pair<Integer, ResourcesKey> key = Pair.create(displayId,
-                    findKeyForResourceImplLocked(resources.getImpl()));
-
-            WeakReference<Display> wd = mResourceDisplays.get(key);
-            if (wd != null) {
-                final Display display = wd.get();
-                if (display != null) {
-                    return display;
-                }
-            }
             final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
             if (dm == null) {
                 // may be null early in system startup
                 return null;
             }
-            final Display display = dm.getCompatibleDisplay(displayId, resources);
-            if (display != null) {
-                mResourceDisplays.put(key, new WeakReference<>(display));
-            }
-            return display;
+            return dm.getCompatibleDisplay(displayId, resources);
         }
     }
 
     private void cleanupResourceImpl(ResourcesKey removedKey) {
-        // Remove any resource to display mapping based on this key.
-        final Iterator<Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>>> iter =
-                mResourceDisplays.entrySet().iterator();
-        while (iter.hasNext()) {
-            final Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>> entry =
-                    iter.next();
-            final ResourcesKey key = entry.getKey().second;
-
-            // Do not touch system resource displays (indicated by a {@code null} key) or
-            // non-matching keys.
-            if (key == null || !key.equals(removedKey)) {
-                continue;
-            }
-
-            iter.remove();
-        }
-
         // Remove resource key to resource impl mapping and flush cache
         final ResourcesImpl res = mResourceImpls.remove(removedKey).get();
 
@@ -887,7 +845,6 @@
             int changes = mResConfiguration.updateFrom(config);
             // Things might have changed in display manager, so clear the cached displays.
             mAdjustedDisplays.clear();
-            mResourceDisplays.clear();
 
             DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
 
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
new file mode 100644
index 0000000..5ed66ca
--- /dev/null
+++ b/core/java/android/app/WallpaperColors.java
@@ -0,0 +1,97 @@
+/*
+ * 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.app;
+
+import android.graphics.Color;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * A class containing information about the colors of a wallpaper.
+ */
+public final class WallpaperColors implements Parcelable {
+
+    public WallpaperColors(Parcel parcel) {
+    }
+
+    /**
+     * Wallpaper color details containing a list of colors and their weights,
+     * as if it were an histogram.
+     * This list can be extracted from a bitmap by the Palette API.
+     *
+     * Dark text support will be calculated internally based on the histogram.
+     *
+     * @param colors list of pairs where each pair contains a color
+     *               and number of occurrences/influence.
+     */
+    public WallpaperColors(List<Pair<Color, Integer>> colors) {
+    }
+
+    /**
+     * Wallpaper color details containing a list of colors and their weights,
+     * as if it were an histogram.
+     * Explicit dark text support.
+     *
+     * @param colors list of pairs where each pair contains a color
+     *               and number of occurrences/influence.
+     * @param supportsDarkText can have dark text on top or not
+     */
+    public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) {
+    }
+
+    public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
+        @Override
+        public WallpaperColors createFromParcel(Parcel in) {
+            return new WallpaperColors(in);
+        }
+
+        @Override
+        public WallpaperColors[] newArray(int size) {
+            return new WallpaperColors[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+
+    /**
+     * List of colors with their occurrences. The bigger the int, the more relevant the color.
+     * @return list of colors paired with their weights.
+     */
+    public List<Pair<Color, Integer>> getColors() {
+        return null;
+    }
+
+    /**
+     * Whether or not dark text is legible on top of this wallpaper.
+     *
+     * @return true if dark text is supported
+     */
+    public boolean supportsDarkText() {
+        return false;
+    }
+}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index aa0eaae..0676bca 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -17,6 +17,8 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RawRes;
 import android.annotation.SystemApi;
 import android.content.ComponentName;
@@ -741,6 +743,43 @@
         return getWallpaperFile(which, mContext.getUserId());
     }
 
+
+    /**
+     * Registers a listener to get notified when the wallpaper colors change.
+     * Callback might be called from an arbitrary background thread.
+     *
+     * @param listener A listener to register
+     */
+    public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
+    }
+
+    /**
+     * Registers a listener to get notified when the wallpaper colors change
+     * @param listener A listener to register
+     * @param handler Where to call it from. Might be called from a background thread
+     *                if null.
+     */
+    public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
+            @Nullable Handler handler) {
+    }
+
+    /**
+     * Stop listening to color updates.
+     * @param callback A callback to unsubscribe
+     */
+    public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) {
+    }
+
+    /**
+     * Get the primary colors of a wallpaper
+     * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or
+     *     {@link #FLAG_LOCK}
+     * @return a list of colors ordered by priority
+     */
+    public @Nullable WallpaperColors getWallpaperColors(int which) {
+        return null;
+    }
+
     /**
      * Version of {@link #getWallpaperFile(int)} that can access the wallpaper data
      * for a given user.  The caller must hold the INTERACT_ACROSS_USERS_FULL
@@ -1732,4 +1771,19 @@
             mLatch.countDown();
         }
     }
+
+    /**
+     * Interface definition for a callback to be invoked when colors change on a wallpaper.
+     */
+    public interface OnColorsChangedListener {
+        /**
+         * Called when colors change.
+         * A {@link android.app.WallpaperColors} object containing a simplified
+         * color histogram will be given.
+         *
+         * @param colors Wallpaper color info
+         * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM}
+         */
+        void onColorsChanged(WallpaperColors colors, int which);
+    }
 }
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java
index f4019ce..9096b47 100644
--- a/core/java/android/app/job/JobService.java
+++ b/core/java/android/app/job/JobService.java
@@ -60,161 +60,24 @@
     public static final String PERMISSION_BIND =
             "android.permission.BIND_JOB_SERVICE";
 
-    /**
-     * Identifier for a message that will result in a call to
-     * {@link #onStartJob(android.app.job.JobParameters)}.
-     */
-    private static final int MSG_EXECUTE_JOB = 0;
-    /**
-     * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
-     */
-    private static final int MSG_STOP_JOB = 1;
-    /**
-     * Message that the client has completed execution of this job.
-     */
-    private static final int MSG_JOB_FINISHED = 2;
-
-    /** Lock object for {@link #mHandler}. */
-    private final Object mHandlerLock = new Object();
-
-    /**
-     * Handler we post jobs to. Responsible for calling into the client logic, and handling the
-     * callback to the system.
-     */
-    @GuardedBy("mHandlerLock")
-    JobHandler mHandler;
-
-    static final class JobInterface extends IJobService.Stub {
-        final WeakReference<JobService> mService;
-
-        JobInterface(JobService service) {
-            mService = new WeakReference<>(service);
-        }
-
-        @Override
-        public void startJob(JobParameters jobParams) throws RemoteException {
-            JobService service = mService.get();
-            if (service != null) {
-                service.ensureHandler();
-                Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
-                m.sendToTarget();
-            }
-        }
-
-        @Override
-        public void stopJob(JobParameters jobParams) throws RemoteException {
-            JobService service = mService.get();
-            if (service != null) {
-                service.ensureHandler();
-                Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
-                m.sendToTarget();
-            }
-
-        }
-    }
-
-    IJobService mBinder;
-
-    /** @hide */
-    void ensureHandler() {
-        synchronized (mHandlerLock) {
-            if (mHandler == null) {
-                mHandler = new JobHandler(getMainLooper());
-            }
-        }
-    }
-
-    /**
-     * Runs on application's main thread - callbacks are meant to offboard work to some other
-     * (app-specified) mechanism.
-     * @hide
-     */
-    class JobHandler extends Handler {
-        JobHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            final JobParameters params = (JobParameters) msg.obj;
-            switch (msg.what) {
-                case MSG_EXECUTE_JOB:
-                    try {
-                        boolean workOngoing = JobService.this.onStartJob(params);
-                        ackStartMessage(params, workOngoing);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Error while executing job: " + params.getJobId());
-                        throw new RuntimeException(e);
-                    }
-                    break;
-                case MSG_STOP_JOB:
-                    try {
-                        boolean ret = JobService.this.onStopJob(params);
-                        ackStopMessage(params, ret);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Application unable to handle onStopJob.", e);
-                        throw new RuntimeException(e);
-                    }
-                    break;
-                case MSG_JOB_FINISHED:
-                    final boolean needsReschedule = (msg.arg2 == 1);
-                    IJobCallback callback = params.getCallback();
-                    if (callback != null) {
-                        try {
-                            callback.jobFinished(params.getJobId(), needsReschedule);
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Error reporting job finish to system: binder has gone" +
-                                    "away.");
-                        }
-                    } else {
-                        Log.e(TAG, "finishJob() called for a nonexistent job id.");
-                    }
-                    break;
-                default:
-                    Log.e(TAG, "Unrecognised message received.");
-                    break;
-            }
-        }
-
-        private void ackStartMessage(JobParameters params, boolean workOngoing) {
-            final IJobCallback callback = params.getCallback();
-            final int jobId = params.getJobId();
-            if (callback != null) {
-                try {
-                     callback.acknowledgeStartMessage(jobId, workOngoing);
-                } catch(RemoteException e) {
-                    Log.e(TAG, "System unreachable for starting job.");
-                }
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
-                }
-            }
-        }
-
-        private void ackStopMessage(JobParameters params, boolean reschedule) {
-            final IJobCallback callback = params.getCallback();
-            final int jobId = params.getJobId();
-            if (callback != null) {
-                try {
-                    callback.acknowledgeStopMessage(jobId, reschedule);
-                } catch(RemoteException e) {
-                    Log.e(TAG, "System unreachable for stopping job.");
-                }
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
-                }
-            }
-        }
-    }
+    private JobServiceEngine mEngine;
 
     /** @hide */
     public final IBinder onBind(Intent intent) {
-        if (mBinder == null) {
-            mBinder = new JobInterface(this);
+        if (mEngine == null) {
+            mEngine = new JobServiceEngine(this) {
+                @Override
+                public boolean onStartJob(JobParameters params) {
+                    return JobService.this.onStartJob(params);
+                }
+
+                @Override
+                public boolean onStopJob(JobParameters params) {
+                    return JobService.this.onStopJob(params);
+                }
+            };
         }
-        return mBinder.asBinder();
+        return mEngine.getBinder();
     }
 
     /**
@@ -269,9 +132,6 @@
      *                        criteria specified at schedule-time. False otherwise.
      */
     public final void jobFinished(JobParameters params, boolean needsReschedule) {
-        ensureHandler();
-        Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
-        m.arg2 = needsReschedule ? 1 : 0;
-        m.sendToTarget();
+        mEngine.jobFinished(params, needsReschedule);
     }
 }
\ No newline at end of file
diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java
new file mode 100644
index 0000000..879212e
--- /dev/null
+++ b/core/java/android/app/job/JobServiceEngine.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app.job;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Helper for implementing a {@link android.app.Service} that interacts with
+ * {@link JobScheduler}.
+ */
+public abstract class JobServiceEngine {
+    private static final String TAG = "JobServiceEngine";
+
+    /**
+     * Identifier for a message that will result in a call to
+     * {@link #onStartJob(android.app.job.JobParameters)}.
+     */
+    private static final int MSG_EXECUTE_JOB = 0;
+    /**
+     * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
+     */
+    private static final int MSG_STOP_JOB = 1;
+    /**
+     * Message that the client has completed execution of this job.
+     */
+    private static final int MSG_JOB_FINISHED = 2;
+
+    /**
+     * Context we are running in.
+     */
+    private final Context mContext;
+
+    private final IJobService mBinder;
+
+    /** Lock object for {@link #mHandler}. */
+    private final Object mHandlerLock = new Object();
+
+    /**
+     * Handler we post jobs to. Responsible for calling into the client logic, and handling the
+     * callback to the system.
+     */
+    @GuardedBy("mHandlerLock")
+    JobHandler mHandler;
+
+    static final class JobInterface extends IJobService.Stub {
+        final WeakReference<JobServiceEngine> mService;
+
+        JobInterface(JobServiceEngine service) {
+            mService = new WeakReference<>(service);
+        }
+
+        @Override
+        public void startJob(JobParameters jobParams) throws RemoteException {
+            JobServiceEngine service = mService.get();
+            if (service != null) {
+                Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
+                m.sendToTarget();
+            }
+        }
+
+        @Override
+        public void stopJob(JobParameters jobParams) throws RemoteException {
+            JobServiceEngine service = mService.get();
+            if (service != null) {
+                Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
+                m.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Runs on application's main thread - callbacks are meant to offboard work to some other
+     * (app-specified) mechanism.
+     * @hide
+     */
+    class JobHandler extends Handler {
+        JobHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final JobParameters params = (JobParameters) msg.obj;
+            switch (msg.what) {
+                case MSG_EXECUTE_JOB:
+                    try {
+                        boolean workOngoing = JobServiceEngine.this.onStartJob(params);
+                        ackStartMessage(params, workOngoing);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error while executing job: " + params.getJobId());
+                        throw new RuntimeException(e);
+                    }
+                    break;
+                case MSG_STOP_JOB:
+                    try {
+                        boolean ret = JobServiceEngine.this.onStopJob(params);
+                        ackStopMessage(params, ret);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Application unable to handle onStopJob.", e);
+                        throw new RuntimeException(e);
+                    }
+                    break;
+                case MSG_JOB_FINISHED:
+                    final boolean needsReschedule = (msg.arg2 == 1);
+                    IJobCallback callback = params.getCallback();
+                    if (callback != null) {
+                        try {
+                            callback.jobFinished(params.getJobId(), needsReschedule);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error reporting job finish to system: binder has gone" +
+                                    "away.");
+                        }
+                    } else {
+                        Log.e(TAG, "finishJob() called for a nonexistent job id.");
+                    }
+                    break;
+                default:
+                    Log.e(TAG, "Unrecognised message received.");
+                    break;
+            }
+        }
+
+        private void ackStartMessage(JobParameters params, boolean workOngoing) {
+            final IJobCallback callback = params.getCallback();
+            final int jobId = params.getJobId();
+            if (callback != null) {
+                try {
+                    callback.acknowledgeStartMessage(jobId, workOngoing);
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for starting job.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
+                }
+            }
+        }
+
+        private void ackStopMessage(JobParameters params, boolean reschedule) {
+            final IJobCallback callback = params.getCallback();
+            final int jobId = params.getJobId();
+            if (callback != null) {
+                try {
+                    callback.acknowledgeStopMessage(jobId, reschedule);
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for stopping job.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a new engine, ready for use.
+     *
+     * @param context The {@link Service} that is creating this engine.
+     */
+    public JobServiceEngine(Context context) {
+        mContext = context;
+        mBinder = new JobInterface(this);
+        mHandler = new JobHandler(mContext.getMainLooper());
+    }
+
+    /**
+     * Retrieve the engine's IPC interface that should be returned by
+     * {@link Service#onBind(Intent)}.
+     */
+    public final IBinder getBinder() {
+        return mBinder.asBinder();
+    }
+
+    /**
+     * Engine's report that a job has started.  See
+     * {@link JobService#onStartJob(JobParameters) JobService.onStartJob} for more information.
+     */
+    public abstract boolean onStartJob(JobParameters params);
+
+    /**
+     * Engine's report that a job has stopped.  See
+     * {@link JobService#onStopJob(JobParameters) JobService.onStopJob} for more information.
+     */
+    public abstract boolean onStopJob(JobParameters params);
+
+    /**
+     * Call in to engine to report that a job has finished executing.  See
+     * {@link JobService#jobFinished(JobParameters, boolean)}  JobService.jobFinished} for more
+     * information.
+     */
+    public final void jobFinished(JobParameters params, boolean needsReschedule) {
+        Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
+        m.arg2 = needsReschedule ? 1 : 0;
+        m.sendToTarget();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 334e88b..582709c 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothGattService;
 import android.bluetooth.le.AdvertiseSettings;
@@ -47,6 +48,9 @@
     void unregisterScanner(in int scannerId);
     void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters,
                    in WorkSource workSource, in List scanStorages, in String callingPackage);
+    void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters,
+                            in String callingPackage);
+    void stopScanForIntent(in PendingIntent intent, in String callingPackage);
     void stopScan(in int scannerId);
     void flushPendingBatchResults(in int scannerId);
 
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index b63c614..b65a7ad 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -17,17 +17,18 @@
 package android.bluetooth.le;
 
 import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
+import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothGatt;
 import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothManager;
-import android.bluetooth.le.IScannerCallback;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.util.Log;
@@ -36,7 +37,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 
 /**
  * This class provides methods to perform scan related operations for Bluetooth LE devices. An
@@ -57,6 +57,27 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
+    /**
+     * Extra containing a list of ScanResults. It can have one or more results if there was no
+     * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
+     * extra will not be available.
+     */
+    public static final String EXTRA_LIST_SCAN_RESULT
+            = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
+
+    /**
+     * Optional extra indicating the error code, if any. The error code will be one of the
+     * SCAN_FAILED_* codes in {@link ScanCallback}.
+     */
+    public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+
+    /**
+     * Optional extra indicating the callback type, which will be one of
+     * ScanSettings.CALLBACK_TYPE_*.
+     * @see ScanCallback#onScanResult(int, ScanResult)
+     */
+    public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+
     private final IBluetoothManager mBluetoothManager;
     private final Handler mHandler;
     private BluetoothAdapter mBluetoothAdapter;
@@ -110,7 +131,27 @@
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public void startScan(List<ScanFilter> filters, ScanSettings settings,
             final ScanCallback callback) {
-        startScan(filters, settings, null, callback, null);
+        startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null);
+    }
+
+    /**
+     * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
+     * the PendingIntent. Use this method of scanning if your process is not always running and it
+     * should be started when scan results are available.
+     *
+     * @param filters Optional list of ScanFilters for finding exact BLE devices.
+     * @param settings Optional settings for the scan.
+     * @param callbackIntent The PendingIntent to deliver the result to.
+     * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
+     * could not be sent.
+     * @see #stopScan(PendingIntent)
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
+            @NonNull PendingIntent callbackIntent) {
+        return startScan(filters,
+                settings != null ? settings : new ScanSettings.Builder().build(),
+                null, null, callbackIntent, null);
     }
 
     /**
@@ -145,23 +186,23 @@
             Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
     public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
                                     final WorkSource workSource, final ScanCallback callback) {
-        startScan(filters, settings, workSource, callback, null);
+        startScan(filters, settings, workSource, callback, null, null);
     }
 
-    private void startScan(List<ScanFilter> filters, ScanSettings settings,
+    private int startScan(List<ScanFilter> filters, ScanSettings settings,
                            final WorkSource workSource, final ScanCallback callback,
+                           final PendingIntent callbackIntent,
                            List<List<ResultStorageDescriptor>> resultStorages) {
         BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        if (callback == null) {
+        if (callback == null && callbackIntent == null) {
             throw new IllegalArgumentException("callback is null");
         }
         if (settings == null) {
             throw new IllegalArgumentException("settings is null");
         }
         synchronized (mLeScanClients) {
-            if (mLeScanClients.containsKey(callback)) {
+            if (callback != null && mLeScanClients.containsKey(callback)) {
                 postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED);
-                return;
             }
             IBluetoothGatt gatt;
             try {
@@ -170,28 +211,34 @@
                 gatt = null;
             }
             if (gatt == null) {
-                postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
-                return;
+                return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
             }
             if (!isSettingsConfigAllowedForScan(settings)) {
-                postCallbackError(callback,
-                        ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
-                return;
+                return postCallbackErrorOrReturn(callback,
+                            ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
             }
             if (!isHardwareResourcesAvailableForScan(settings)) {
-                postCallbackError(callback,
-                        ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
-                return;
+                return postCallbackErrorOrReturn(callback,
+                            ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
             }
             if (!isSettingsAndFilterComboAllowed(settings, filters)) {
-                postCallbackError(callback,
+                return postCallbackErrorOrReturn(callback,
                         ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
-                return;
             }
-            BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
-                    settings, workSource, callback, resultStorages);
-            wrapper.startRegisteration();
+            if (callback != null) {
+                BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
+                        settings, workSource, callback, resultStorages);
+                wrapper.startRegistration();
+            } else {
+                try {
+                    gatt.startScanForIntent(callbackIntent, settings, filters,
+                            ActivityThread.currentOpPackageName());
+                } catch (RemoteException e) {
+                    return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
+                }
+            }
         }
+        return ScanCallback.NO_ERROR;
     }
 
     /**
@@ -215,6 +262,25 @@
     }
 
     /**
+     * Stops an ongoing Bluetooth LE scan started using a PendingIntent.
+     * <p>
+     * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param callbackIntent The PendingIntent that was used to start the scan.
+     * @see #startScan(List, ScanSettings, PendingIntent)
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public void stopScan(PendingIntent callbackIntent) {
+        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
+        IBluetoothGatt gatt;
+        try {
+            gatt = mBluetoothManager.getBluetoothGatt();
+            gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
      * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
      * will be delivered through the {@code callback}.
@@ -252,7 +318,7 @@
             scanFilters.add(filter.getFilter());
             scanStorages.add(filter.getStorageDescriptors());
         }
-        startScan(scanFilters, settings, null, callback, scanStorages);
+        startScan(scanFilters, settings, null, callback, null, scanStorages);
     }
 
     /**
@@ -295,7 +361,7 @@
             mResultStorages = resultStorages;
         }
 
-        public void startRegisteration() {
+        public void startRegistration() {
             synchronized (this) {
                 // Scan stopped.
                 if (mScannerId == -1) return;
@@ -399,7 +465,6 @@
                     mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
                 }
             });
-
         }
 
         @Override
@@ -453,6 +518,15 @@
         }
     }
 
+    private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
+        if (callback == null) {
+            return errorCode;
+        } else {
+            postCallbackError(callback, errorCode);
+            return ScanCallback.NO_ERROR;
+        }
+    }
+
     private void postCallbackError(final ScanCallback callback, final int errorCode) {
         mHandler.post(new Runnable() {
             @Override
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
index 61b2e78..aff2e90 100644
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ b/core/java/android/bluetooth/le/ScanCallback.java
@@ -50,6 +50,8 @@
      */
     public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5;
 
+    static final int NO_ERROR = 0;
+
     /**
      * Callback when a BLE advertisement has been found.
      *
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 4d788e7..e50b2a9 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -22,11 +22,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.service.notification.NotificationListenerService;
 import android.util.Log;
 
 import java.util.Collections;
@@ -195,22 +197,47 @@
         }
     }
 
-    /** @hide */
-    public void requestNotificationAccess() {
+    /**
+     * Request notification access for the given component.
+     *
+     * The given component must follow the protocol specified in {@link NotificationListenerService}
+     *
+     * Only components from the same {@link ComponentName#getPackageName package} as the calling app
+     * are allowed.
+     *
+     * Your app must have an association with a device before calling this API
+     */
+    public void requestNotificationAccess(ComponentName component) {
         if (!checkFeaturePresent()) {
             return;
         }
-        //TODO implement
-        throw new UnsupportedOperationException("Not yet implemented");
+        try {
+            mService.requestNotificationAccess(component).send();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (PendingIntent.CanceledException e) {
+            throw new RuntimeException(e);
+        }
     }
 
-    /** @hide */
-    public boolean haveNotificationAccess() {
+    /**
+     * Check whether the given component can access the notifications via a
+     * {@link NotificationListenerService}
+     *
+     * Your app must have an association with a device before calling this API
+     *
+     * @param component the name of the component
+     * @return whether the given component has the notification listener permission
+     */
+    public boolean hasNotificationAccess(ComponentName component) {
         if (!checkFeaturePresent()) {
             return false;
         }
-        //TODO implement
-        throw new UnsupportedOperationException("Not yet implemented");
+        try {
+            return mService.hasNotificationAccess(component);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     private boolean checkFeaturePresent() {
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 7798406..d395208 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -16,8 +16,10 @@
 
 package android.companion;
 
+import android.app.PendingIntent;
 import android.companion.IFindDeviceCallback;
 import android.companion.AssociationRequest;
+import android.content.ComponentName;
 
 /**
  * Interface for communication with the core companion device manager service.
@@ -32,7 +34,6 @@
     List<String> getAssociations(String callingPackage, int userId);
     void disassociate(String deviceMacAddress, String callingPackage);
 
-    //TODO add these
-//    boolean haveNotificationAccess(String packageName);
-//    oneway void requestNotificationAccess(String packageName);
+    boolean hasNotificationAccess(in ComponentName component);
+    PendingIntent requestNotificationAccess(in ComponentName component);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 0da4f8d..5ca4fa3 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3424,8 +3424,10 @@
 
     /**
      * Deprecated - use ACTION_FACTORY_RESET instead.
+     * @hide
      */
     @Deprecated
+    @SystemApi
     public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
 
     /**
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 147df76..bbc942a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -632,4 +632,6 @@
     void deletePreloadsFileCache();
 
     ComponentName getInstantAppResolverSettingsComponent();
+
+    ComponentName getInstantAppInstallerComponent();
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e5c8f0d..09906be 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -6275,9 +6275,19 @@
      * Return the {@link ComponentName} of the activity providing Settings for the Instant App
      * resolver.
      *
-     * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
+     * @see {@link android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
      * @hide
      */
     @SystemApi
     public abstract ComponentName getInstantAppResolverSettingsComponent();
+
+    /**
+     * Return the {@link ComponentName} of the activity responsible for installing instant
+     * applications.
+     *
+     * @see {@link android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE}
+     * @hide
+     */
+    @SystemApi
+    public abstract ComponentName getInstantAppInstallerComponent();
 }
diff --git a/core/java/android/net/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java
new file mode 100644
index 0000000..7aafc93
--- /dev/null
+++ b/core/java/android/net/MatchAllNetworkSpecifier.java
@@ -0,0 +1,80 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * MatchAllNetworkSpecifier is a marker class used by NetworkFactory classes to indicate
+ * that they accept (match) any network specifier in requests.
+ *
+ * The class must never be used as part of a network request (those semantics aren't specified).
+ *
+ * @hide
+ */
+public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+    /**
+     * Utility method which verifies that the ns argument is not a MatchAllNetworkSpecifier and
+     * throws an IllegalArgumentException if it is.
+     */
+    public static void checkNotMatchAllNetworkSpecifier(NetworkSpecifier ns) {
+        if (ns instanceof MatchAllNetworkSpecifier) {
+            throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted");
+        }
+    }
+
+    public boolean satisfiedBy(NetworkSpecifier other) {
+        /*
+         * The method is called by a NetworkRequest to see if it is satisfied by a proposed
+         * network (e.g. as offered by a network factory). Since MatchAllNetweorkSpecifier must
+         * not be used in network requests this method should never be called.
+         */
+        throw new IllegalStateException(
+                "MatchAllNetworkSpecifier must not be used in NetworkRequests");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return o instanceof MatchAllNetworkSpecifier;
+    }
+
+    @Override
+    public int hashCode() {
+        return 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        // Nothing to write.
+    }
+
+    public static final Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR =
+            new Parcelable.Creator<MatchAllNetworkSpecifier>() {
+        public MatchAllNetworkSpecifier createFromParcel(Parcel in) {
+            return new MatchAllNetworkSpecifier();
+        }
+        public MatchAllNetworkSpecifier[] newArray(int size) {
+            return new MatchAllNetworkSpecifier[size];
+        }
+    };
+}
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index 4409d0a..b4ef695 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -56,7 +56,7 @@
      *
      * @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)}
      *                    for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1.
-     * @param badging  {@see ScoredNetwork#Badging}, retrieved from
+     * @param badging  {@see NetworkBadging#Badging}, retrieved from
      *                 {@link ScoredNetwork#calculateBadge(int)}.
      * @param theme The theme for the current application, may be null.
      * @return Drawable for the given icon
@@ -140,7 +140,7 @@
      * <p>This badge should be displayed with the badge signal resource retrieved from
      * {@link #getBadgedWifiSignalResource(int)}.
      *
-     * @param badging {@see ScoredNetwork#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
+     * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
      * @return the @DrawableRes for the icon or {@link View#NO_ID} for
      *         {@link NetworkBadging#BADGING_NONE}
      * @throws IllegalArgumentException for an invalid badging value.
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a594bef..afca0b0 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -18,9 +18,11 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.text.TextUtils;
+
 import com.android.internal.util.BitUtils;
 
+import java.util.Objects;
+
 /**
  * This class represents the capabilities of a network.  This is used both to specify
  * needs to {@link ConnectivityManager} and when inspecting a network.
@@ -33,6 +35,8 @@
  * all cellular based connections are metered and all Wi-Fi based connections are not.
  */
 public final class NetworkCapabilities implements Parcelable {
+    private static final String TAG = "NetworkCapabilities";
+
     /**
      * @hide
      */
@@ -205,19 +209,6 @@
             (1 << NET_CAPABILITY_FOREGROUND);
 
     /**
-     * Network specifier for factories which want to match any network specifier
-     * (NS) in a request. Behavior:
-     * <li>Empty NS in request matches any network factory NS</li>
-     * <li>Empty NS in the network factory NS only matches a request with an
-     * empty NS</li>
-     * <li>"*" (this constant) NS in the network factory matches requests with
-     * any NS</li>
-     *
-     * @hide
-     */
-    public static final String MATCH_ALL_REQUESTS_NETWORK_SPECIFIER = "*";
-
-    /**
      * Network capabilities that are not allowed in NetworkRequests. This exists because the
      * NetworkFactory / NetworkAgent model does not deal well with the situation where a
      * capability's presence cannot be known in advance. If such a capability is requested, then we
@@ -579,63 +570,56 @@
                 this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
     }
 
-    private String mNetworkSpecifier;
+    private NetworkSpecifier mNetworkSpecifier = null;
+
     /**
      * Sets the optional bearer specific network specifier.
      * This has no meaning if a single transport is also not specified, so calling
      * this without a single transport set will generate an exception, as will
      * subsequently adding or removing transports after this is set.
      * </p>
-     * The interpretation of this {@code String} is bearer specific and bearers that use
-     * it should document their particulars.  For example, Bluetooth may use some sort of
-     * device id while WiFi could used SSID and/or BSSID.  Cellular may use carrier SPN (name)
-     * or Subscription ID.
      *
-     * @param networkSpecifier An {@code String} of opaque format used to specify the bearer
-     *                         specific network specifier where the bearer has a choice of
-     *                         networks.
+     * @param networkSpecifier A concrete, parcelable framework class that extends
+     *                         NetworkSpecifier.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
-    public NetworkCapabilities setNetworkSpecifier(String networkSpecifier) {
-        if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) {
+    public NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+        if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) {
             throw new IllegalStateException("Must have a single transport specified to use " +
                     "setNetworkSpecifier");
         }
+
         mNetworkSpecifier = networkSpecifier;
+
         return this;
     }
 
     /**
      * Gets the optional bearer specific network specifier.
      *
-     * @return The optional {@code String} specifying the bearer specific network specifier.
-     *         See {@link #setNetworkSpecifier}.
+     * @return The optional {@link NetworkSpecifier} specifying the bearer specific network
+     *         specifier. See {@link #setNetworkSpecifier}.
      * @hide
      */
-    public String getNetworkSpecifier() {
+    public NetworkSpecifier getNetworkSpecifier() {
         return mNetworkSpecifier;
     }
 
     private void combineSpecifiers(NetworkCapabilities nc) {
-        String otherSpecifier = nc.getNetworkSpecifier();
-        if (TextUtils.isEmpty(otherSpecifier)) return;
-        if (TextUtils.isEmpty(mNetworkSpecifier) == false) {
+        if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) {
             throw new IllegalStateException("Can't combine two networkSpecifiers");
         }
-        setNetworkSpecifier(otherSpecifier);
+        setNetworkSpecifier(nc.mNetworkSpecifier);
     }
+
     private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
-        return (TextUtils.isEmpty(mNetworkSpecifier) ||
-                mNetworkSpecifier.equals(nc.mNetworkSpecifier) ||
-                MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier));
+        return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier)
+                || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier;
     }
+
     private boolean equalsSpecifier(NetworkCapabilities nc) {
-        if (TextUtils.isEmpty(mNetworkSpecifier)) {
-            return TextUtils.isEmpty(nc.mNetworkSpecifier);
-        } else {
-            return mNetworkSpecifier.equals(nc.mNetworkSpecifier);
-        }
+        return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier);
     }
 
     /**
@@ -797,7 +781,7 @@
                 ((int)(mTransportTypes >> 32) * 7) +
                 (mLinkUpBandwidthKbps * 11) +
                 (mLinkDownBandwidthKbps * 13) +
-                (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17) +
+                Objects.hashCode(mNetworkSpecifier) * 17 +
                 (mSignalStrength * 19));
     }
 
@@ -811,7 +795,7 @@
         dest.writeLong(mTransportTypes);
         dest.writeInt(mLinkUpBandwidthKbps);
         dest.writeInt(mLinkDownBandwidthKbps);
-        dest.writeString(mNetworkSpecifier);
+        dest.writeParcelable((Parcelable) mNetworkSpecifier, flags);
         dest.writeInt(mSignalStrength);
     }
 
@@ -825,7 +809,7 @@
                 netCap.mTransportTypes = in.readLong();
                 netCap.mLinkUpBandwidthKbps = in.readInt();
                 netCap.mLinkDownBandwidthKbps = in.readInt();
-                netCap.mNetworkSpecifier = in.readString();
+                netCap.mNetworkSpecifier = in.readParcelable(null);
                 netCap.mSignalStrength = in.readInt();
                 return netCap;
             }
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index cb78009..95a8bb4 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.Objects;
 
@@ -259,10 +260,27 @@
          *                         networks.
          */
         public Builder setNetworkSpecifier(String networkSpecifier) {
-            if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) {
-                throw new IllegalArgumentException("Invalid network specifier - must not be '"
-                        + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
-            }
+            /*
+             * A StringNetworkSpecifier does not accept null or empty ("") strings. When network
+             * specifiers were strings a null string and an empty string were considered equivalent.
+             * Hence no meaning is attached to a null or empty ("") string.
+             */
+            return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null
+                    : new StringNetworkSpecifier(networkSpecifier));
+        }
+
+        /**
+         * Sets the optional bearer specific network specifier.
+         * This has no meaning if a single transport is also not specified, so calling
+         * this without a single transport set will generate an exception, as will
+         * subsequently adding or removing transports after this is set.
+         * </p>
+         *
+         * @param networkSpecifier A concrete, parcelable framework class that extends
+         *                         NetworkSpecifier.
+         */
+        public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+            MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(networkSpecifier);
             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
             return this;
         }
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
new file mode 100644
index 0000000..87a2b05
--- /dev/null
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -0,0 +1,36 @@
+/*
+ * 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.net;
+
+/**
+ * Describes specific properties of a network for use in a {@link NetworkRequest}.
+ *
+ * Applications cannot instantiate this class by themselves, but can obtain instances of
+ * subclasses of this class via other APIs.
+ */
+public abstract class NetworkSpecifier {
+    /** @hide */
+    public NetworkSpecifier() {}
+
+    /**
+     * Returns true if a request with this {@link NetworkSpecifier} is satisfied by a network
+     * with the given NetworkSpecifier.
+     *
+     * @hide
+     */
+    public abstract boolean satisfiedBy(NetworkSpecifier other);
+}
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index a664a8b..666da0a 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -73,29 +73,6 @@
     /** A {@link NetworkKey} uniquely identifying this network. */
     public final NetworkKey networkKey;
 
-    // TODO(b/35323372): Delete these once external references are switched.
-    /** @deprecated Use {@link NetworkBadging#Badging} instead. */
-    @Deprecated
-    @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Badging {}
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_NONE} instead. */
-    @Deprecated
-    public static final int BADGING_NONE = 0;
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_SD} instead. */
-    @Deprecated
-    public static final int BADGING_SD = 10;
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_HD} instead. */
-    @Deprecated
-    public static final int BADGING_HD = 20;
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_4K} instead. */
-    @Deprecated
-    public static final int BADGING_4K = 30;
-
     /**
      * The {@link RssiCurve} representing the scores for this network based on the RSSI.
      *
diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
new file mode 100644
index 0000000..cb7f6bf
--- /dev/null
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -0,0 +1,79 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/** @hide */
+public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+    /**
+     * Arbitrary string used to pass (additional) information to the network factory.
+     */
+    public final String specifier;
+
+    public StringNetworkSpecifier(String specifier) {
+        Preconditions.checkStringNotEmpty(specifier);
+        this.specifier = specifier;
+    }
+
+    @Override
+    public boolean satisfiedBy(NetworkSpecifier other) {
+        return equals(other);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof StringNetworkSpecifier)) return false;
+        return TextUtils.equals(specifier, ((StringNetworkSpecifier) o).specifier);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(specifier);
+    }
+
+    @Override
+    public String toString() {
+        return specifier;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(specifier);
+    }
+
+    public static final Parcelable.Creator<StringNetworkSpecifier> CREATOR =
+            new Parcelable.Creator<StringNetworkSpecifier>() {
+        public StringNetworkSpecifier createFromParcel(Parcel in) {
+            return new StringNetworkSpecifier(in.readString());
+        }
+        public StringNetworkSpecifier[] newArray(int size) {
+            return new StringNetworkSpecifier[size];
+        }
+    };
+}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 15bd175..ff0bc69 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -16,9 +16,15 @@
 
 package android.os;
 
+import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.Slog;
+
 import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FunctionalUtils;
+import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+
 import libcore.io.IoUtils;
 
 import java.io.FileDescriptor;
@@ -26,7 +32,6 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Modifier;
-import java.util.function.Supplier;
 
 /**
  * Base class for a remotable object, the core part of a lightweight
@@ -251,14 +256,23 @@
      * Convenience method for running the provided action enclosed in
      * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}
      *
+     * Any exception thrown by the given action will be caught and rethrown after the call to
+     * {@link #restoreCallingIdentity}
+     *
      * @hide
      */
-    public static final void withCleanCallingIdentity(Runnable action) {
+    public static final void withCleanCallingIdentity(ThrowingRunnable action) {
         long callingIdentity = clearCallingIdentity();
+        Throwable throwableToPropagate = null;
         try {
             action.run();
+        } catch (Throwable throwable) {
+            throwableToPropagate = throwable;
         } finally {
             restoreCallingIdentity(callingIdentity);
+            if (throwableToPropagate != null) {
+                throw ExceptionUtils.propagate(throwableToPropagate);
+            }
         }
     }
 
@@ -266,14 +280,24 @@
      * Convenience method for running the provided action enclosed in
      * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result
      *
+     * Any exception thrown by the given action will be caught and rethrown after the call to
+     * {@link #restoreCallingIdentity}
+     *
      * @hide
      */
-    public static final <T> T withCleanCallingIdentity(Supplier<T> action) {
+    public static final <T> T withCleanCallingIdentity(ThrowingSupplier<T> action) {
         long callingIdentity = clearCallingIdentity();
+        Throwable throwableToPropagate = null;
         try {
             return action.get();
+        } catch (Throwable throwable) {
+            throwableToPropagate = throwable;
+            return null; // overridden by throwing in finally block
         } finally {
             restoreCallingIdentity(callingIdentity);
+            if (throwableToPropagate != null) {
+                throw ExceptionUtils.propagate(throwableToPropagate);
+            }
         }
     }
 
diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java
index 3dfedea..a3dc947 100644
--- a/core/java/android/provider/SettingsStringUtil.java
+++ b/core/java/android/provider/SettingsStringUtil.java
@@ -23,6 +23,7 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.function.Function;
@@ -80,6 +81,12 @@
                 return s;
             }
 
+            public static String addAll(String delimitedElements, Collection<String> elements) {
+                final ColonDelimitedSet<String> set
+                        = new ColonDelimitedSet.OfStrings(delimitedElements);
+                return set.addAll(elements) ? set.toString() : delimitedElements;
+            }
+
             public static String add(String delimitedElements, String element) {
                 final ColonDelimitedSet<String> set
                         = new ColonDelimitedSet.OfStrings(delimitedElements);
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index a4d3fb2..5e49b8f 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -34,6 +34,8 @@
 
 import com.android.internal.os.SomeArgs;
 
+import java.util.List;
+
 //TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
 //life-cycle (and how state could be maintained on server-side) is well documented.
 
@@ -103,24 +105,22 @@
         }
 
         @Override
-        public void onFillRequest(AssistStructure structure, Bundle extras,
-                IFillCallback callback, int flags) {
+        public void onFillRequest(FillRequest request, IFillCallback callback) {
             ICancellationSignal transport = CancellationSignal.createTransport();
             try {
                 callback.onCancellable(transport);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
-            mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure,
-                    CancellationSignal.fromTransport(transport), extras, callback)
+            mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request,
+                    CancellationSignal.fromTransport(transport), callback)
                     .sendToTarget();
         }
 
         @Override
-        public void onSaveRequest(AssistStructure structure, Bundle extras,
-                ISaveCallback callback) {
-            mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
-                    extras, callback).sendToTarget();
+        public void onSaveRequest(SaveRequest request, ISaveCallback callback) {
+            mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request,
+                    callback).sendToTarget();
         }
     };
 
@@ -131,23 +131,20 @@
                 break;
             } case MSG_ON_FILL_REQUEST: {
                 final SomeArgs args = (SomeArgs) msg.obj;
-                final AssistStructure structure = (AssistStructure) args.arg1;
+                final FillRequest request = (FillRequest) args.arg1;
                 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
-                final Bundle extras = (Bundle) args.arg3;
-                final IFillCallback callback = (IFillCallback) args.arg4;
-                final FillCallback fillCallback = new FillCallback(callback);
-                final int flags = msg.arg1;
+                final IFillCallback callback = (IFillCallback) args.arg3;
+                final FillCallback fillCallback = new FillCallback(callback, request.getId());
                 args.recycle();
-                onFillRequest(structure, extras, flags, cancellation, fillCallback);
+                onFillRequest(request, cancellation, fillCallback);
                 break;
             } case MSG_ON_SAVE_REQUEST: {
                 final SomeArgs args = (SomeArgs) msg.obj;
-                final AssistStructure structure = (AssistStructure) args.arg1;
-                final Bundle extras = (Bundle) args.arg2;
-                final ISaveCallback callback = (ISaveCallback) args.arg3;
+                final SaveRequest request = (SaveRequest) args.arg1;
+                final ISaveCallback callback = (ISaveCallback) args.arg2;
                 final SaveCallback saveCallback = new SaveCallback(callback);
                 args.recycle();
-                onSaveRequest(structure, extras, saveCallback);
+                onSaveRequest(request, saveCallback);
                 break;
             } case MSG_DISCONNECT: {
                 onDisconnected();
@@ -198,6 +195,28 @@
      * or {@link FillCallback#onFailure(CharSequence)})
      * to notify the result of the request.
      *
+     * @param request the {@link FillRequest request} to handle.
+     *        See {@link FillResponse} for examples of multiple-sections requests.
+     * @param cancellationSignal signal for observing cancellation requests. The system will use
+     *     this to notify you that the fill result is no longer needed and you should stop
+     *     handling this fill request in order to save resources.
+     * @param callback object used to notify the result of the request.
+     */
+    public void onFillRequest(@NonNull FillRequest request,
+            @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
+        onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(),
+                cancellationSignal, callback);
+    }
+
+    /**
+     * Called by the Android system do decide if an {@link Activity} can be autofilled by the
+     * service.
+     *
+     * <p>Service must call one of the {@link FillCallback} methods (like
+     * {@link FillCallback#onSuccess(FillResponse)}
+     * or {@link FillCallback#onFailure(CharSequence)})
+     * to notify the result of the request.
+     *
      * @param structure {@link Activity}'s view structure.
      * @param data bundle containing data passed by the service in a last call to
      *        {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
@@ -211,6 +230,7 @@
      *     handling this fill request in order to save resources.
      * @param callback object used to notify the result of the request.
      */
+    @Deprecated
     public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
             int flags, @NonNull CancellationSignal cancellationSignal,
             @NonNull FillCallback callback);
@@ -222,6 +242,23 @@
      * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
      * to notify the result of the request.
      *
+     * @param request the {@link SaveRequest request} to handle.
+     *        See {@link FillResponse} for examples of multiple-sections requests.
+     * @param callback object used to notify the result of the request.
+     */
+    public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
+        List<FillContext> contexts = request.getFillContexts();
+        onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
+                request.getClientState(), callback);
+    }
+
+    /**
+     * Called when user requests service to save the fields of an {@link Activity}.
+     *
+     * <p>Service must call one of the {@link SaveCallback} methods (like
+     * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
+     * to notify the result of the request.
+     *
      * @param structure {@link Activity}'s view structure.
      * @param data bundle containing data passed by the service in a last call to
      *        {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
@@ -231,6 +268,7 @@
      *        See {@link FillResponse} for examples of multiple-sections requests.
      * @param callback object used to notify the result of the request.
      */
+    @Deprecated
     public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
             @NonNull SaveCallback callback);
 
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index e8ad14f..a009be8 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -27,11 +27,13 @@
  */
 public final class FillCallback {
     private final IFillCallback mCallback;
+    private final int mRequestId;
     private boolean mCalled;
 
     /** @hide */
-    public FillCallback(IFillCallback callback) {
+    public FillCallback(IFillCallback callback, int requestId) {
         mCallback = callback;
+        mRequestId = requestId;
     }
 
     /**
@@ -47,7 +49,7 @@
         assertNotCalled();
         mCalled = true;
         try {
-            mCallback.onSuccess(response);
+            mCallback.onSuccess(response, mRequestId);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
new file mode 100644
index 0000000..2efa08c
--- /dev/null
+++ b/core/java/android/service/autofill/FillContext.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.NonNull;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class represents a context for each fill request made via {@link
+ * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}.
+ * It contains a snapshot of the UI state, the view ids that were returned by
+ * the {@link AutofillService autofill service} as both required to trigger a save
+ * and optional that can be saved, and the id of the corresponding {@link
+ * FillRequest}.
+ * <p>
+ * This context allows you to inspect the values for the interesting views
+ * in the context they appeared. Also a reference to the corresponding fill
+ * request is useful to store meta-data in the client state bundle passed
+ * to {@link FillResponse.Builder#setClientState(Bundle)} to avoid interpreting
+ * the UI state again while saving.
+ */
+public final class FillContext implements Parcelable {
+    private final int mRequestId;
+    private final @NonNull AssistStructure mStructure;
+
+    /** @hide */
+    public FillContext(int requestId, @NonNull AssistStructure structure) {
+        mRequestId = requestId;
+        mStructure = structure;
+    }
+
+    private FillContext(Parcel parcel) {
+        this(parcel.readInt(), parcel.readParcelable(null));
+    }
+
+    /**
+     * Gets the id of the {@link FillRequest fill request} this context
+     * corresponds to. This is useful to associate your custom client
+     * state with every request to avoid reinterpreting the UI when saving
+     * user data.
+     *
+     * @return The request id.
+     */
+    public int getRequestId() {
+        return mRequestId;
+    }
+
+    /**
+     * @return The screen content.
+     */
+    public AssistStructure getStructure() {
+        return mStructure;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mRequestId);
+        parcel.writeParcelable(mStructure, flags);
+    }
+
+    public static final Parcelable.Creator<FillContext> CREATOR =
+            new Parcelable.Creator<FillContext>() {
+        @Override
+        public FillContext createFromParcel(Parcel parcel) {
+            return new FillContext(parcel);
+        }
+
+        @Override
+        public FillContext[] newArray(int size) {
+            return new FillContext[size];
+        }
+    };
+}
diff --git a/core/java/android/service/autofill/FillRequest.aidl b/core/java/android/service/autofill/FillRequest.aidl
new file mode 100644
index 0000000..2b1a8fe
--- /dev/null
+++ b/core/java/android/service/autofill/FillRequest.aidl
@@ -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.
+ */
+
+package android.service.autofill;
+
+parcelable FillRequest;
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
new file mode 100644
index 0000000..aa6db4d
--- /dev/null
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.service.autofill;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class represents a request to an {@link AutofillService autofill provider}
+ * to interpret the screen and provide information to the system which views are
+ * interesting for saving and what are the possible ways to fill the inputs on
+ * the screen if applicable.
+ *
+ * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+ */
+public final class FillRequest implements Parcelable {
+    private static AtomicInteger sIdCounter = new AtomicInteger();
+
+    /**
+     * Indicates autofill was explicitly requested by the user.
+     */
+    public static final int FLAG_MANUAL_REQUEST = 0x1;
+
+    /** @hide */
+    @IntDef(
+        flag = true,
+        value = {FLAG_MANUAL_REQUEST})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface RequestFlags{}
+
+    private final int mId;
+    private final @RequestFlags int mFlags;
+    private final @NonNull AssistStructure mStructure;
+    private final @Nullable Bundle mClientState;
+
+    /** @hide */
+    public FillRequest(@NonNull AssistStructure structure,
+            @Nullable Bundle clientState, @RequestFlags int flags) {
+        this(sIdCounter.incrementAndGet(), structure, clientState, flags);
+    }
+
+    private FillRequest(@NonNull Parcel parcel) {
+        mId = parcel.readInt();
+        mStructure = parcel.readParcelable(null);
+        mClientState = parcel.readBundle();
+        mFlags = parcel.readInt();
+    }
+
+    private FillRequest(int id, @NonNull AssistStructure structure,
+            @Nullable Bundle clientState, @RequestFlags int flags) {
+        mId = id;
+        mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST);
+        mStructure = Preconditions.checkNotNull(structure, "structure");
+        mClientState = clientState;
+    }
+
+    /**
+     * @return The unique id of this request.
+     */
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * @return The flags associated with this request.
+     *
+     * @see #FLAG_MANUAL_REQUEST
+     */
+    public @RequestFlags int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * @return The structure capturing the UI state.
+     */
+    public @NonNull AssistStructure getStructure() {
+        return mStructure;
+    }
+
+    /**
+     * Gets the extra client state returned from the last {@link
+     * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+     * fill request}.
+     * <p>
+     * Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+     * save request} is made the client state is cleared.
+     *
+     * @return The client state.
+     */
+    public @Nullable Bundle getClientState() {
+        return mClientState;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mId);
+        parcel.writeParcelable(mStructure, flags);
+        parcel.writeBundle(mClientState);
+        parcel.writeInt(mFlags);
+    }
+
+    public static final Parcelable.Creator<FillRequest> CREATOR =
+            new Parcelable.Creator<FillRequest>() {
+        @Override
+        public FillRequest createFromParcel(Parcel parcel) {
+            return new FillRequest(parcel);
+        }
+
+        @Override
+        public FillRequest[] newArray(int size) {
+            return new FillRequest[size];
+        }
+    };
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index eab0d4c..8c8060a 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -132,25 +132,25 @@
  */
 public final class FillResponse implements Parcelable {
 
-    private final ArrayList<Dataset> mDatasets;
-    private final SaveInfo mSaveInfo;
-    private final Bundle mExtras;
-    private final RemoteViews mPresentation;
-    private final IntentSender mAuthentication;
-    private AutofillId[] mAuthenticationIds;
+    private final @Nullable ArrayList<Dataset> mDatasets;
+    private final @Nullable SaveInfo mSaveInfo;
+    private final @Nullable Bundle mClientState;
+    private final @Nullable RemoteViews mPresentation;
+    private final @Nullable IntentSender mAuthentication;
+    private final @Nullable AutofillId[] mAuthenticationIds;
 
     private FillResponse(@NonNull Builder builder) {
         mDatasets = builder.mDatasets;
         mSaveInfo = builder.mSaveInfo;
-        mExtras = builder.mExtras;
+        mClientState = builder.mCLientState;
         mPresentation = builder.mPresentation;
         mAuthentication = builder.mAuthentication;
         mAuthenticationIds = builder.mAuthenticationIds;
     }
 
     /** @hide */
-    public @Nullable Bundle getExtras() {
-        return mExtras;
+    public @Nullable Bundle getClientState() {
+        return mClientState;
     }
 
     /** @hide */
@@ -185,7 +185,7 @@
     public static final class Builder {
         private ArrayList<Dataset> mDatasets;
         private SaveInfo mSaveInfo;
-        private Bundle mExtras;
+        private Bundle mCLientState;
         private RemoteViews mPresentation;
         private IntentSender mAuthentication;
         private AutofillId[] mAuthenticationIds;
@@ -289,23 +289,35 @@
             return this;
         }
 
+        @Deprecated
+        public Builder setExtras(@Nullable Bundle extras) {
+            throwIfDestroyed();
+            mCLientState = extras;
+            return this;
+        }
+
         /**
-         * Sets a {@link Bundle} that will be passed to subsequent APIs that
+         * Sets a {@link Bundle state} that will be passed to subsequent APIs that
          * manipulate this response. For example, they are passed to subsequent
          * calls to {@link AutofillService#onFillRequest(
          * android.app.assist.AssistStructure, Bundle, int,
          * android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest(
-         * android.app.assist.AssistStructure, Bundle, SaveCallback)}.
+         * android.app.assist.AssistStructure, Bundle, SaveCallback)}. You can use
+         * this to store intermediate state that is persistent across multiple
+         * fill requests and the subsequent save request.
          *
          * <p>If this method is called on multiple {@link FillResponse} objects for the same
          * activity, just the latest bundle is passed back to the service.
          *
-         * @param extras The response extras.
+         * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+         * save request} is made the client state is cleared.
+         *
+         * @param clientState The custom client state.
          * @return This builder.
          */
-        public Builder setExtras(Bundle extras) {
+        public Builder setClientState(@Nullable Bundle clientState) {
             throwIfDestroyed();
-            mExtras = extras;
+            mCLientState = clientState;
             return this;
         }
 
@@ -344,7 +356,7 @@
         return new StringBuilder(
                 "FillResponse: [datasets=").append(mDatasets)
                 .append(", saveInfo=").append(mSaveInfo)
-                .append(", hasExtras=").append(mExtras != null)
+                .append(", clientState=").append(mClientState != null)
                 .append(", hasPresentation=").append(mPresentation != null)
                 .append(", hasAuthentication=").append(mAuthentication != null)
                 .append(", authenticationSize=").append(mAuthenticationIds != null
@@ -365,7 +377,7 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeTypedArrayList(mDatasets, flags);
         parcel.writeParcelable(mSaveInfo, flags);
-        parcel.writeParcelable(mExtras, flags);
+        parcel.writeParcelable(mClientState, flags);
         parcel.writeParcelableArray(mAuthenticationIds, flags);
         parcel.writeParcelable(mAuthentication, flags);
         parcel.writeParcelable(mPresentation, flags);
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index a8d86ca..23a1a3f 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -16,10 +16,10 @@
 
 package android.service.autofill;
 
-import android.app.assist.AssistStructure;
-import android.os.Bundle;
+import android.service.autofill.FillRequest;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
+import android.service.autofill.SaveRequest;
 import com.android.internal.os.IResultReceiver;
 
 /**
@@ -29,8 +29,6 @@
  */
 oneway interface IAutoFillService {
     void onConnectedStateChanged(boolean connected);
-    void onFillRequest(in AssistStructure structure, in Bundle extras,
-            in IFillCallback callback, int flags);
-    void onSaveRequest(in AssistStructure structure, in Bundle extras,
-            in ISaveCallback callback);
+    void onFillRequest(in FillRequest request, in IFillCallback callback);
+    void onSaveRequest(in SaveRequest request, in ISaveCallback callback);
 }
diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl
index 2bb3e9a..688ac84 100644
--- a/core/java/android/service/autofill/IFillCallback.aidl
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -27,6 +27,6 @@
  */
 interface IFillCallback {
     void onCancellable(in ICancellationSignal cancellation);
-    void onSuccess(in FillResponse response);
+    void onSuccess(in FillResponse response, int requestId);
     void onFailure(CharSequence message);
 }
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 4ad0f08..258d257 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -140,7 +140,19 @@
      */
     public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
 
-    private final int mType;
+    /** @hide */
+    @IntDef(
+       flag = true,
+       value = {
+               SAVE_DATA_TYPE_GENERIC,
+               SAVE_DATA_TYPE_PASSWORD,
+               SAVE_DATA_TYPE_ADDRESS,
+               SAVE_DATA_TYPE_CREDIT_CARD,
+               SAVE_DATA_TYPE_EMAIL_ADDRESS})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface SaveDataType{}
+
+    private final @SaveDataType int mType;
     private final CharSequence mNegativeActionTitle;
     private final IntentSender mNegativeActionListener;
     private final AutofillId[] mRequiredIds;
@@ -177,7 +189,7 @@
     }
 
     /** @hide */
-    public int getType() {
+    public @SaveDataType int getType() {
         return mType;
     }
 
@@ -191,7 +203,7 @@
      */
     public static final class Builder {
 
-        private final int mType;
+        private final @SaveDataType int mType;
         private CharSequence mNegativeActionTitle;
         private IntentSender mNegativeActionListener;
         // TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone
@@ -215,7 +227,7 @@
          *
          * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty.
          */
-        public Builder(int type, @NonNull AutofillId[] requiredIds) {
+        public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
             if (false) {// TODO(b/33197203): re-move when clients use it
             Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0,
                     "must have at least one required id: " + Arrays.toString(requiredIds));
@@ -230,7 +242,7 @@
          * // TODO(b/33197203): make sure is removed when clients migrated
          */
         @Deprecated
-        public Builder(int type) {
+        public Builder(@SaveDataType int type) {
             this(type, null);
         }
 
diff --git a/core/java/android/service/autofill/SaveRequest.aidl b/core/java/android/service/autofill/SaveRequest.aidl
new file mode 100644
index 0000000..7789b577
--- /dev/null
+++ b/core/java/android/service/autofill/SaveRequest.aidl
@@ -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.
+ */
+
+package android.service.autofill;
+
+parcelable SaveRequest;
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
new file mode 100644
index 0000000..9de9315
--- /dev/null
+++ b/core/java/android/service/autofill/SaveRequest.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 android.service.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents a request to an {@link AutofillService
+ * autofill provider} to save applicable data entered by the user.
+ *
+ * @see AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+ */
+public final class SaveRequest implements Parcelable {
+    private final @NonNull ArrayList<FillContext> mFillContexts;
+    private final @Nullable Bundle mClientState;
+
+    /** @hide */
+    public SaveRequest(@NonNull ArrayList<FillContext> fillContexts,
+            @Nullable Bundle clientState) {
+        mFillContexts = Preconditions.checkNotNull(fillContexts, "fillContexts");
+        mClientState = clientState;
+    }
+
+    private SaveRequest(@NonNull Parcel parcel) {
+        this(parcel.readTypedArrayList(null), parcel.readBundle());
+    }
+
+    /**
+     * @return The contexts associated with each previous fill request.
+     */
+    public @NonNull List<FillContext> getFillContexts() {
+        return mFillContexts;
+    }
+
+    /**
+     * Gets the extra client state returned from the last {@link
+     * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}
+     * fill request}.
+     *
+     * @return The client state.
+     */
+    public @Nullable Bundle getClientState() {
+        return mClientState;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeTypedArrayList(mFillContexts, flags);
+        parcel.writeBundle(mClientState);
+    }
+
+    public static final Creator<SaveRequest> CREATOR =
+            new Creator<SaveRequest>() {
+        @Override
+        public SaveRequest createFromParcel(Parcel parcel) {
+            return new SaveRequest(parcel);
+        }
+
+        @Override
+        public SaveRequest[] newArray(int size) {
+            return new SaveRequest[size];
+        }
+    };
+}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 6bbb0ff..98780a7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -16,6 +16,8 @@
 
 package android.service.wallpaper;
 
+import android.annotation.Nullable;
+import android.app.WallpaperColors;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.util.MergedConfiguration;
@@ -542,6 +544,24 @@
          */
         public void onSurfaceDestroyed(SurfaceHolder holder) {
         }
+
+        /**
+         * Notifies the engine that wallpaper colors changed significantly.
+         * This will trigger a {@link #onComputeWallpaperColors()} call.
+         */
+        public void invalidateColors() {
+        }
+
+        /**
+         * Notifies the system about what colors the wallpaper is using.
+         * You might return null if no color information is available at the moment. In that case
+         * you might want to call {@link #invalidateColors()} in a near future.
+         *
+         * @return List of wallpaper colors and their weights.
+         */
+        public @Nullable WallpaperColors onComputeWallpaperColors() {
+            return null;
+        }
         
         protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
             out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a522652..172ad8d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -109,7 +109,6 @@
 import android.widget.ScrollBarDrawable;
 
 import com.android.internal.R;
-import com.android.internal.util.Preconditions;
 import com.android.internal.view.TooltipPopup;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.ScrollBarUtils;
@@ -954,41 +953,6 @@
 
     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
 
-    /** @hide */
-    @IntDef({
-            AUTOFILL_MODE_INHERIT,
-            AUTOFILL_MODE_AUTO,
-            AUTOFILL_MODE_MANUAL
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AutofillMode {}
-
-    /**
-     * This view inherits the autofill state from it's parent. If there is no parent it is
-     * {@link #AUTOFILL_MODE_AUTO}.
-     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
-     * {@code android:autofillMode}.
-     */
-    public static final int AUTOFILL_MODE_INHERIT = 0;
-
-    /**
-     * Allows this view to automatically trigger an autofill request when it get focus.
-     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
-     * {@code android:autofillMode}.
-     */
-    public static final int AUTOFILL_MODE_AUTO = 1;
-
-    /**
-     * Do not trigger an autofill request if this view is focused. The user can still force
-     * an autofill request.
-     * <p>This does not prevent this field from being autofilled if an autofill operation is
-     * triggered from a different view.</p>
-     *
-     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code
-     * android:autofillMode}.
-     */
-    public static final int AUTOFILL_MODE_MANUAL = 2;
-
     /**
      * This view contains an email address.
      *
@@ -2762,7 +2726,7 @@
      *                 1                 PFLAG3_IS_AUTOFILLED
      *                1                  PFLAG3_FINGER_DOWN
      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
-     *             11                    PFLAG3_AUTO_FILL_MODE_MASK
+     *             __                    unused
      *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
@@ -2992,23 +2956,6 @@
     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
 
     /**
-     * Shift for the place where the autofill mode is stored in the pflags
-     *
-     * @see #getAutofillMode()
-     * @see #setAutofillMode(int)
-     */
-    private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
-
-    /**
-     * Mask for autofill modes
-     *
-     * @see #getAutofillMode()
-     * @see #setAutofillMode(int)
-     */
-    private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
-            | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
-
-    /**
      * Shift for the bits in {@link #mPrivateFlags3} related to the
      * "importantForAutofill" attribute.
      */
@@ -5055,11 +5002,6 @@
                         setFocusedByDefault(a.getBoolean(attr, true));
                     }
                     break;
-                case R.styleable.View_autofillMode:
-                    if (a.peekValue(attr) != null) {
-                        setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
-                    }
-                    break;
                 case R.styleable.View_autofillHints:
                     if (a.peekValue(attr) != null) {
                         CharSequence[] rawHints = null;
@@ -6849,8 +6791,7 @@
     }
 
     private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
-        if (isAutofillable() && isAttachedToWindow()
-                && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
+        if (isAutofillable() && isAttachedToWindow()) {
             AutofillManager afm = getAutofillManager();
             if (afm != null) {
                 if (enter && hasWindowFocus() && isFocused()) {
@@ -9159,21 +9100,6 @@
     }
 
     /**
-     * Set autofill mode for the view.
-     *
-     * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
-     *                     or {@link #AUTOFILL_MODE_MANUAL}.
-     * @attr ref android.R.styleable#View_autofillMode
-     */
-    public void setAutofillMode(@AutofillMode int autofillMode) {
-        Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
-                AUTOFILL_MODE_MANUAL, "autofillMode");
-
-        mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
-        mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
-    }
-
-    /**
      * Sets the hints that helps the autofill service to select the appropriate data to fill the
      * view.
      *
@@ -9810,48 +9736,6 @@
     }
 
     /**
-     * Returns the autofill mode for this view.
-     *
-     * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
-     * {@link #AUTOFILL_MODE_MANUAL}.
-     * @attr ref android.R.styleable#View_autofillMode
-     */
-    @ViewDebug.ExportedProperty(mapping = {
-            @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
-            @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
-            @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
-            })
-    @AutofillMode
-    public int getAutofillMode() {
-        return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
-    }
-
-    /**
-     * Returns the resolved autofill mode for this view.
-     *
-     * This is the same as {@link #getAutofillMode()} but if the mode is
-     * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
-     *
-     * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
-     *         fill mode can not be resolved e.g. {@link #getAutofillMode()} is
-     *         {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
-     *         {@link #AUTOFILL_MODE_AUTO} is returned.
-     */
-    public @AutofillMode int getResolvedAutofillMode() {
-        @AutofillMode int autofillMode = getAutofillMode();
-
-        if (autofillMode == AUTOFILL_MODE_INHERIT) {
-            if (mParent == null) {
-                return AUTOFILL_MODE_AUTO;
-            } else {
-                return mParent.getResolvedAutofillMode();
-            }
-        } else {
-            return autofillMode;
-        }
-    }
-
-    /**
      * Find the nearest view in the specified direction that can take focus.
      * This does not actually give focus to that view.
      *
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d5aab48..cc11cb8 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -659,17 +659,4 @@
      * @return true if the action was consumed by this ViewParent
      */
     public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
-
-    /**
-     * Return the resolved autofill mode.
-     *
-     * @return One of {@link View#AUTOFILL_MODE_AUTO}, {@link View#AUTOFILL_MODE_MANUAL} if the
-     *         autofill mode can be resolved. If the autofill mode cannot be resolved
-     *         {@link View#AUTOFILL_MODE_AUTO}.
-     *
-     * @see View#getResolvedAutofillMode()
-     */
-    default @View.AutofillMode int getResolvedAutofillMode() {
-        return View.AUTOFILL_MODE_AUTO;
-    }
 }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 570f968..ec6559c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -101,7 +101,10 @@
     // Public flags start from the lowest bit
     /**
      * Indicates autofill was explicitly requested by the user.
+     *
+     * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST}
      */
+    @Deprecated
     public static final int FLAG_MANUAL_REQUEST = 0x1;
 
     // Private flags start from the highest bit
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 2f12e9b..28d9fcf 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -155,7 +155,7 @@
     public static final int IME_ACTION_PREVIOUS = 0x00000007;
 
     /**
-     * Flag of {@link #imeOptions}: used to request that the IME does not update any personalized
+     * Flag of {@link #imeOptions}: used to request that the IME should not update any personalized
      * data such as typing history and personalized language model based on what the user typed on
      * this text editing object.  Typical use cases are:
      * <ul>
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 35ffa71..999a908 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -67,10 +67,15 @@
 
     @Override
     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        event.setClassName(Dialog.class.getName());
-        event.setPackageName(getPackageName());
+        return dispatchPopulateAccessibilityEvent(this, event);
+    }
 
-        ViewGroup.LayoutParams params = getWindow().getAttributes();
+    public static boolean dispatchPopulateAccessibilityEvent(Activity act,
+            AccessibilityEvent event) {
+        event.setClassName(Dialog.class.getName());
+        event.setPackageName(act.getPackageName());
+
+        ViewGroup.LayoutParams params = act.getWindow().getAttributes();
         boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) &&
                 (params.height == ViewGroup.LayoutParams.MATCH_PARENT);
         event.setFullScreen(isFullScreen);
@@ -86,8 +91,7 @@
      * @see #mAlertParams
      */
     protected void setupAlert() {
-        mAlertParams.apply(mAlert);
-        mAlert.installContent();
+        mAlert.installContent(mAlertParams);
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 95c291a..46cb546 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -247,6 +247,11 @@
         return false;
     }
 
+    public void installContent(AlertParams params) {
+        params.apply(this);
+        installContent();
+    }
+
     public void installContent() {
         int contentView = selectContentView();
         mWindow.setContentView(contentView);
diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
new file mode 100644
index 0000000..4ce6f60
--- /dev/null
+++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
@@ -0,0 +1,37 @@
+/*
+ * 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.notification;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+public final class NotificationAccessConfirmationActivityContract {
+    private static final ComponentName COMPONENT_NAME = new ComponentName(
+            "com.android.settings",
+            "com.android.settings.notification.NotificationAccessConfirmationActivity");
+    public static final String EXTRA_USER_ID = "user_id";
+    public static final String EXTRA_COMPONENT_NAME = "component_name";
+    public static final String EXTRA_PACKAGE_TITLE = "package_title";
+
+    public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) {
+        return new Intent()
+                .setComponent(COMPONENT_NAME)
+                .putExtra(EXTRA_USER_ID, userId)
+                .putExtra(EXTRA_COMPONENT_NAME, component)
+                .putExtra(EXTRA_PACKAGE_TITLE, packageTitle);
+    }
+}
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 183945c..96b443d 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.util;
 
+import static com.android.internal.util.ArrayUtils.isEmpty;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
@@ -64,7 +66,7 @@
      */
     public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
             Function<? super I, ? extends O> f) {
-        if (cur == null || cur.isEmpty()) return Collections.emptyList();
+        if (isEmpty(cur)) return Collections.emptyList();
         final ArrayList<O> result = new ArrayList<>();
         for (int i = 0; i < cur.size(); i++) {
             result.add(f.apply(cur.get(i)));
@@ -73,6 +75,30 @@
     }
 
     /**
+     * {@link #map(List, Function)} + {@link #filter(List, java.util.function.Predicate)}
+     *
+     * Calling this is equivalent (but more memory efficient) to:
+     *
+     * {@code
+     *      filter(
+     *          map(cur, f),
+     *          i -> { i != null })
+     * }
+     */
+    public static @NonNull <I, O> List<O> mapNotNull(@Nullable List<I> cur,
+            Function<? super I, ? extends O> f) {
+        if (isEmpty(cur)) return Collections.emptyList();
+        final ArrayList<O> result = new ArrayList<>();
+        for (int i = 0; i < cur.size(); i++) {
+            O transformed = f.apply(cur.get(i));
+            if (transformed != null) {
+                result.add(transformed);
+            }
+        }
+        return result;
+    }
+
+    /**
      * Returns the given list, or an immutable empty list if the provided list is null
      *
      * This can be used to guaranty null-safety without paying the price of extra allocations
@@ -94,7 +120,7 @@
      * Returns the elements of the given list that are of type {@code c}
      */
     public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
-        if (ArrayUtils.isEmpty(list)) return Collections.emptyList();
+        if (isEmpty(list)) return Collections.emptyList();
         ArrayList<T> result = null;
         for (int i = 0; i < list.size(); i++) {
             final Object item = list.get(i);
@@ -120,7 +146,7 @@
      */
     public static @Nullable <T> T find(@Nullable List<T> items,
             java.util.function.Predicate<T> predicate) {
-        if (ArrayUtils.isEmpty(items)) return null;
+        if (isEmpty(items)) return null;
         for (int i = 0; i < items.size(); i++) {
             final T item = items.get(i);
             if (predicate.test(item)) return item;
@@ -145,11 +171,17 @@
      * {@link Collections#emptyList}
      */
     public static @NonNull <T> List<T> remove(@Nullable List<T> cur, T val) {
-        if (cur == null || cur == Collections.emptyList()) {
-            return Collections.emptyList();
+        if (isEmpty(cur)) {
+            return emptyIfNull(cur);
         }
         cur.remove(val);
         return cur;
     }
 
+    /**
+     * @return a list that will not be affected by mutations to the given original list.
+     */
+    public static @NonNull <T> List<T> copyOf(@Nullable List<T> cur) {
+        return isEmpty(cur) ? Collections.emptyList() : new ArrayList<>(cur);
+    }
 }
diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java
new file mode 100644
index 0000000..9aeb041
--- /dev/null
+++ b/core/java/com/android/internal/util/FunctionalUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.util.function.Supplier;
+
+/**
+ * Utilities specific to functional programming
+ */
+public class FunctionalUtils {
+    private FunctionalUtils() {}
+
+    /**
+     * An equivalent of {@link Runnable} that allows throwing checked exceptions
+     *
+     * This can be used to specify a lambda argument without forcing all the checked exceptions
+     * to be handled within it
+     */
+    @FunctionalInterface
+    public interface ThrowingRunnable {
+        void run() throws Exception;
+    }
+
+    /**
+     * An equivalent of {@link Supplier} that allows throwing checked exceptions
+     *
+     * This can be used to specify a lambda argument without forcing all the checked exceptions
+     * to be handled within it
+     */
+    @FunctionalInterface
+    public interface ThrowingSupplier<T> {
+        T get() throws Exception;
+    }
+}
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 4e6857a..e5d5716 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -49,6 +49,23 @@
     }
 
     /**
+     * Ensures that an expression checking an argument is true.
+     *
+     * @param expression the expression to check
+     * @param messageTemplate a printf-style message template to use if the check fails; will
+     *     be converted to a string using {@link String#format(String, Object...)}
+     * @param messageArgs arguments for {@code messageTemplate}
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(boolean expression,
+            final String messageTemplate,
+            final Object... messageArgs) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+        }
+    }
+
+    /**
      * Ensures that an string reference passed as a parameter to the calling
      * method is not empty.
      *
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 1883ecb..9491a1e 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -59,7 +59,7 @@
         cPackageInfo[i] = cString;
         env->ReleaseStringUTFChars(element, cString);
     }
-    int32_t status = VintfObject::CheckCompatibility(cPackageInfo, false /* mount */);
+    int32_t status = VintfObject::CheckCompatibility(cPackageInfo);
     return status;
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 000c8c4..8869593 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3556,6 +3556,11 @@
                 android:process=":ui">
         </activity>
 
+        <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
+                  android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+                  android:excludeFromRecents="true">
+        </activity>
+
         <receiver android:name="com.android.server.BootReceiver"
                 android:systemUserOnly="true">
             <intent-filter android:priority="1000">
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 67f6d19..4fb21fa 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1371,6 +1371,22 @@
              Corresponds to
              {@link android.view.inputmethod.EditorInfo#IME_ACTION_PREVIOUS}. -->
         <flag name="actionPrevious" value="0x00000007" />
+        <!-- Used to request that the IME should not update any personalized data such as typing
+             history and personalized language model based on what the user typed on this text
+             editing object. Typical use cases are:
+             <ul>
+                 <li>When the application is in a special mode, where user's activities are expected
+                 to be not recorded in the application's history. Some web browsers and chat
+                 applications may have this kind of modes.</li>
+                 <li>When storing typing history does not make much sense.  Specifying this flag in
+                 typing games may help to avoid typing history from being filled up with words that
+                 the user is less likely to type in their daily life.  Another example is that when
+                 the application already knows that the expected input is not a valid word (e.g. a
+                 promotion code that is not a valid word in any natural language).</li>
+             </ul>
+             <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may
+             not respect it.</p> -->
+        <flag name="flagNoPersonalizedLearning" value="0x1000000" />
         <!-- Used to request that the IME never go
              into fullscreen mode.  Applications need to be aware that the flag is not
              a guarantee, and not all IMEs will respect it.
@@ -2304,18 +2320,7 @@
             <enum name="auto" value="0x00000010" />
         </attr>
 
-        <!-- Controls the autofill behavior for this view. -->
-        <attr name="autofillMode">
-            <!-- Inherit the behavior from the parent. If there is no parent it is auto. This is the
-                 default value for this attribute.-->
-            <enum name="inherit" value="0" />
-            <!-- Allows this view to automatically trigger an autofill request when it get focus.
-                 -->
-            <enum name="auto" value="1" />
-            <!-- Do not trigger an autofill request when this view is focused. The user can still
-                 manually force an autofill request for this view. -->
-            <enum name="manual" value="2" />
-        </attr>
+        <attr name="__removed3" />
 
         <!-- Describes the content of a view so that a autofill service can fill in the appropriate
              data. Multiple hints can be combined in a comma separated list or an array of strings
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d6ed178..213d6ca 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2797,7 +2797,7 @@
         <public name="numericModifiers" />
         <public name="fontProviderAuthority" />
         <public name="fontProviderQuery" />
-        <public name="autofillMode" />
+        <public name="__removed3" />
         <public name="primaryContentAlpha" />
         <public name="secondaryContentAlpha" />
         <public name="requiredFeature" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0821674..bd35073 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3000,6 +3000,8 @@
 
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
+    <!-- Do not translate. Default access point SSID used for local only hotspot -->
+    <string name="wifi_localhotspot_configure_ssid_default" translatable="false">AndroidShare</string>
 
     <!-- A notification is shown the first time a connection is attempted on an app owned AP -->
     <!-- title for this message -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 603e376..f2da845 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -19,6 +19,9 @@
   <!-- Private symbols that we need to reference from framework code.  See
        frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
        this.
+
+       Can be referenced in java code as: com.android.internal.R.<type>.<name>
+       and in layout xml as: "@*android:<type>/<name>"
   -->
   <java-symbol type="id" name="account_name" />
   <java-symbol type="id" name="account_row_icon" />
@@ -1003,6 +1006,7 @@
   <java-symbol type="string" name="wifi_p2p_turnon_message" />
   <java-symbol type="string" name="wifi_p2p_frequency_conflict_message" />
   <java-symbol type="string" name="wifi_tether_configure_ssid_default" />
+  <java-symbol type="string" name="wifi_localhotspot_configure_ssid_default" />
   <java-symbol type="string" name="wifi_watchdog_network_disabled" />
   <java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
   <java-symbol type="string" name="imei" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ec653d0..7f07f03 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -40,6 +40,7 @@
 
     <privapp-permissions package="com.android.defcontainer">
         <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
+        <permission name="android.permission.ALLOCATE_AGGRESSIVE"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
     </privapp-permissions>
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index e628d18..6cab56c 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -23,12 +23,12 @@
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaMetricsSet;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.view.Surface;
 
 import java.io.IOException;
@@ -3188,20 +3188,19 @@
     /**
      *  Return Metrics data about the current codec instance.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media being handled by this instance of MediaCodec
-     * The attributes are descibed in {@link MediaMetricsSet.MediaCodec}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
-     *  Additional vendor-specific fields may also be present in
-     *  the return value.
+     * Additional vendor-specific fields may also be present in
+     * the return value.
      */
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     /**
      * Change a video encoder's target bitrate on the fly. The value is an
@@ -3660,4 +3659,80 @@
             private final ByteBuffer mData;
         }
     }
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the codec being used
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String CODEC = "android.media.mediacodec.codec";
+
+        /**
+         * Key to extract the MIME type
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE = "android.media.mediacodec.mime";
+
+        /**
+         * Key to extract what the codec mode
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String. Values will be one of the constants
+         * {@link #MODE_AUDIO} or {@link #MODE_VIDEO}.
+         */
+        public static final String MODE = "android.media.mediacodec.mode";
+
+        /**
+         * The value returned for the key {@link #MODE} when the
+         * codec is a audio codec.
+         */
+        public static final String MODE_AUDIO = "audio";
+
+        /**
+         * The value returned for the key {@link #MODE} when the
+         * codec is a video codec.
+         */
+        public static final String MODE_VIDEO = "video";
+
+        /**
+         * Key to extract the flag indicating whether the codec is running
+         * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         * A 0 indicates decoder; 1 indicates encoder.
+         */
+        public static final String ENCODER = "android.media.mediacodec.encoder";
+
+        /**
+         * Key to extract the flag indicating whether the codec is running
+         * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String SECURE = "android.media.mediacodec.secure";
+
+        /**
+         * Key to extract the width (in pixels) of the video track
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String WIDTH = "android.media.mediacodec.width";
+
+        /**
+         * Key to extract the height (in pixels) of the video track
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String HEIGHT = "android.media.mediacodec.height";
+
+        /**
+         * Key to extract the rotation (in degrees) to properly orient the video
+         * from the {@link MediaCodec#getMetrics} return.
+         * The value is a integer.
+         */
+        public static final String ROTATION = "android.media.mediacodec.rotation";
+
+    }
 }
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index a0a6a1e..fe461be 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -25,10 +25,10 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.media.MediaHTTPService;
-import android.media.MediaMetricsSet;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.PersistableBundle;
 
 import com.android.internal.util.Preconditions;
 
@@ -689,22 +689,21 @@
     /**
      *  Return Metrics data about the current media container.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media container being handled by this instance
      * of MediaExtractor.
-     * The attributes are descibed in {@link MediaMetricsSet.MediaExtractor}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
 
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     private static native final void native_init();
     private native final void native_setup();
@@ -718,4 +717,32 @@
     private MediaCas mMediaCas;
 
     private long mNativeContext;
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the container format
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String FORMAT = "android.media.mediaextractor.fmt";
+
+        /**
+         * Key to extract the container MIME type
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE = "android.media.mediaextractor.mime";
+
+        /**
+         * Key to extract the number of tracks in the container
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String TRACKS = "android.media.mediaextractor.ntrk";
+
+    }
+
 }
diff --git a/media/java/android/media/MediaMetricsSet.java b/media/java/android/media/MediaMetricsSet.java
deleted file mode 100644
index 5ecbee2..0000000
--- a/media/java/android/media/MediaMetricsSet.java
+++ /dev/null
@@ -1,491 +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.media;
-
-import android.os.Bundle;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.Runnable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.UUID;
-import java.util.Vector;
-
-
-/**
- * MediaMetricsSet contains the results returned by the getMetrics()
- * methods defined in other Media classes such as
- * {@link MediaCodec}, {@link MediaExtractor}, {@link MediaPlayer},
- * and {@link MediaRecorder}.
- *
- * MediaMetricsSet behaves similarly to a {@link Bundle}. It contains
- * a set of keys and values.
- * Methods such as {@link #getInt} and {@link #getString} are provided
- * to extract values of the corresponding types.
- * The {@link #keySet} method can be used to discover all of the keys
- * that are present in the particular instance.
- *
- */
-public final class MediaMetricsSet
-{
-
-    /**
-     * This MediaCodec class holds the constants defining keys related to
-     * the metrics for a MediaCodec.
-     */
-    public final static class MediaCodec
-    {
-        private MediaCodec() {}
-
-        /**
-         * Key to extract the codec being used
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_CODEC = "android.media.mediacodec.codec";
-
-        /**
-         * Key to extract the MIME type
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME = "android.media.mediacodec.mime";
-
-        /**
-         * Key to extract what the codec mode
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is a String. Values will be one of the constants
-	 * MODE_AUDIO or MODE_VIDEO.
-         */
-        public static final String KEY_MODE = "android.media.mediacodec.mode";
-
-	/**
-	 * The value returned for the key {@link #KEY_MODE} when the
-	 * codec is a audio codec.
-	 */
-        public static final String MODE_AUDIO = "audio";
-
-	/**
-	 * The value returned for the key {@link #KEY_MODE} when the
-	 * codec is a video codec.
-	 */
-        public static final String MODE_VIDEO = "video";
-
-        /**
-         * Key to extract the flag indicating whether the codec is running
-         * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         * A 0 indicates decoder; 1 indicates encoder.
-         */
-        public static final String KEY_ENCODER = "android.media.mediacodec.encoder";
-
-        /**
-         * Key to extract the flag indicating whether the codec is running
-         * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_SECURE = "android.media.mediacodec.secure";
-
-        /**
-         * Key to extract the width (in pixels) of the video track
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_WIDTH = "android.media.mediacodec.width";
-
-        /**
-         * Key to extract the height (in pixels) of the video track
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_HEIGHT = "android.media.mediacodec.height";
-
-        /**
-         * Key to extract the rotation (in degrees) to properly orient the video
-         * from the {@link MediaCodec#getMetrics} return.
-         * The value is a integer.
-         */
-        public static final String KEY_ROTATION = "android.media.mediacodec.rotation";
-
-    }
-
-    /**
-     * This class holds the constants defining keys related to
-     * the metrics for a MediaExtractor.
-     */
-    public final static class MediaExtractor
-    {
-        private MediaExtractor() {}
-
-        /**
-         * Key to extract the container format
-         * from the {@link MediaExtractor#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_FORMAT = "android.media.mediaextractor.fmt";
-
-        /**
-         * Key to extract the container MIME type
-         * from the {@link MediaExtractor#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME = "android.media.mediaextractor.mime";
-
-        /**
-         * Key to extract the number of tracks in the container
-         * from the {@link MediaExtractor#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-
-    }
-
-    /**
-     * This class holds the constants defining keys related to
-     * the metrics for a MediaPlayer.
-     */
-    public final static class MediaPlayer
-    {
-        private MediaPlayer() {}
-
-        /**
-         * Key to extract the MIME type of the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-
-        /**
-         * Key to extract the codec being used to decode the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-
-        /**
-         * Key to extract the width (in pixels) of the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_WIDTH = "android.media.mediaplayer.width";
-
-        /**
-         * Key to extract the height (in pixels) of the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_HEIGHT = "android.media.mediaplayer.height";
-
-        /**
-         * Key to extract the count of video frames played
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_FRAMES = "android.media.mediaplayer.frames";
-
-        /**
-         * Key to extract the count of video frames dropped
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-
-        /**
-         * Key to extract the MIME type of the audio track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-
-        /**
-         * Key to extract the codec being used to decode the audio track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-
-        /**
-         * Key to extract the duration (in milliseconds) of the
-         * media being played
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a long.
-         */
-        public static final String KEY_DURATION = "android.media.mediaplayer.durationMs";
-
-        /**
-         * Key to extract the playing time (in milliseconds) of the
-         * media being played
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a long.
-         */
-        public static final String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-
-        /**
-         * Key to extract the count of errors encountered while
-         * playing the media
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_ERRORS = "android.media.mediaplayer.err";
-
-        /**
-         * Key to extract an (optional) error code detected while
-         * playing the media
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-
-    }
-
-    /**
-     * This class holds the constants defining keys related to
-     * the metrics for a MediaRecorder.
-     */
-    public final static class MediaRecorder
-    {
-        private MediaRecorder() {}
-
-        /**
-         * Key to extract the audio bitrate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-
-        /**
-         * Key to extract the number of audio channels
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-
-        /**
-         * Key to extract the audio samplerate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-
-        /**
-         * Key to extract the audio timescale
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-
-        /**
-         * Key to extract the video capture frame rate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is a double.
-         */
-        public static final String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-
-        /**
-         * Key to extract the video capture framerate enable value
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-
-        /**
-         * Key to extract the intended playback frame rate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-
-        /**
-         * Key to extract the height (in pixels) of the captured video
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_HEIGHT = "android.media.mediarecorder.height";
-
-        /**
-         * Key to extract the recorded movies time units
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         * A value of 1000 indicates that the movie's timing is in milliseconds.
-         */
-        public static final String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-
-        /**
-         * Key to extract the rotation (in degrees) to properly orient the video
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_ROTATION = "android.media.mediarecorder.rotation";
-
-        /**
-         * Key to extract the video bitrate from being used
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-
-        /**
-         * Key to extract the value for how often video iframes are generated
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-
-        /**
-         * Key to extract the video encoding level
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-
-        /**
-         * Key to extract the video encoding profile
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-
-        /**
-         * Key to extract the recorded video time units
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         * A value of 1000 indicates that the video's timing is in milliseconds.
-         */
-        public static final String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-
-        /**
-         * Key to extract the width (in pixels) of the captured video
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_WIDTH = "android.media.mediarecorder.width";
-
-    }
-
-    /*
-     * Methods that we want
-     */
-
-    private Bundle mBundle;
-
-    MediaMetricsSet(Bundle bundle) {
-        mBundle = bundle;
-    }
-
-    /**
-     * Returns the number of mappings contained in this Bundle.
-     *
-     * @return the number of mappings as an int.
-     */
-    public int size() {
-        return mBundle.size();
-    }
-
-    /**
-     * Returns true if the mapping of this MediaMetricsSet is empty,
-     * false otherwise.
-     */
-    public boolean isEmpty() {
-        return mBundle.isEmpty();
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist
-     * @return a double value
-     */
-    public double getDouble(String key, double defaultValue) {
-        return mBundle.getDouble(key, defaultValue);
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist
-     * @return an int value
-     */
-    public int getInt(String key, int defaultValue) {
-        return mBundle.getInt(key, defaultValue);
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist
-     * @return a long value
-     */
-    public long getLong(String key, long defaultValue) {
-        return mBundle.getLong(key, defaultValue);
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key or if a null
-     * value is explicitly associated with the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist or if a null
-     *     value is associated with the given key.
-     * @return the String value associated with the given key, or defaultValue
-     *     if no valid String object is currently mapped to that key.
-     */
-    public String getString(String key, String defaultValue) {
-        return mBundle.getString(key, defaultValue);
-    }
-
-    /**
-     * Returns a Set containing the Strings used as keys in this Bundle.
-     *
-     * @return a Set of String keys
-     */
-    public Set<String> keySet() {
-        return mBundle.keySet();
-    }
-
-
-
-    public String toString() {
-        return mBundle.toString();
-    }
-
-}
-
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 71a968b..9386246 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -33,6 +33,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.PowerManager;
 import android.os.SystemProperties;
@@ -48,7 +49,6 @@
 import android.media.AudioManager;
 import android.media.MediaDrm;
 import android.media.MediaFormat;
-import android.media.MediaMetricsSet;
 import android.media.MediaTimeProvider;
 import android.media.PlaybackParams;
 import android.media.SubtitleController;
@@ -1491,20 +1491,19 @@
     /**
      * Return Metrics data about the current player.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media being handled by this instance of MediaPlayer
-     * The attributes are descibed in {@link MediaMetricsSet.MediaPlayer}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     /**
      * Checks whether the MediaPlayer is playing.
@@ -5418,4 +5417,98 @@
             }
         }
     }
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the MIME type of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+
+        /**
+         * Key to extract the codec being used to decode the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+
+        /**
+         * Key to extract the width (in pixels) of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String WIDTH = "android.media.mediaplayer.width";
+
+        /**
+         * Key to extract the height (in pixels) of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String HEIGHT = "android.media.mediaplayer.height";
+
+        /**
+         * Key to extract the count of video frames played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String FRAMES = "android.media.mediaplayer.frames";
+
+        /**
+         * Key to extract the count of video frames dropped
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+
+        /**
+         * Key to extract the MIME type of the audio track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+
+        /**
+         * Key to extract the codec being used to decode the audio track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+
+        /**
+         * Key to extract the duration (in milliseconds) of the
+         * media being played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a long.
+         */
+        public static final String DURATION = "android.media.mediaplayer.durationMs";
+
+        /**
+         * Key to extract the playing time (in milliseconds) of the
+         * media being played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a long.
+         */
+        public static final String PLAYING = "android.media.mediaplayer.playingMs";
+
+        /**
+         * Key to extract the count of errors encountered while
+         * playing the media
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String ERRORS = "android.media.mediaplayer.err";
+
+        /**
+         * Key to extract an (optional) error code detected while
+         * playing the media
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String ERROR_CODE = "android.media.mediaplayer.errcode";
+
+    }
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 4675e32..997d562 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -20,14 +20,15 @@
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.hardware.Camera;
-import android.media.MediaMetricsSet;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.util.Log;
 import android.view.Surface;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.RandomAccessFile;
@@ -92,6 +93,7 @@
 
     private String mPath;
     private FileDescriptor mFd;
+    private File mFile;
     private EventHandler mEventHandler;
     private OnErrorListener mOnErrorListener;
     private OnInfoListener mOnInfoListener;
@@ -804,10 +806,26 @@
     public void setOutputFile(FileDescriptor fd) throws IllegalStateException
     {
         mPath = null;
+        mFile = null;
         mFd = fd;
     }
 
     /**
+     * Pass in the file object to be written. Call this after setOutputFormat() but before prepare().
+     * File should be seekable. After setting the next output file, application should not use the
+     * file until {@link #stop}. Application is responsible for cleaning up unused files after
+     * {@link #stop} is called.
+     *
+     * @param file the file object to be written into.
+     */
+    public void setOutputFile(File file)
+    {
+        mPath = null;
+        mFd = null;
+        mFile = file;
+    }
+
+    /**
      * Sets the next output file descriptor to be used when the maximum filesize is reached
      * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
      * must be seekable and writable. After setting the next output file, application should not
@@ -842,15 +860,16 @@
     public void setOutputFile(String path) throws IllegalStateException
     {
         mFd = null;
+        mFile = null;
         mPath = path;
     }
 
     /**
-     * Sets the next output file path to be used when the maximum filesize is reached
-     * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File should
-     * be seekable. After setting the next output file, application should not use the file
-     * referenced by this file descriptor until {@link #stop}. Application must call this
-     * after receiving on the {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
+     * Sets the next output file to be used when the maximum filesize is reached on the prior
+     * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable.
+     * After setting the next output file, application should not use the file until {@link #stop}.
+     * Application must call this after receiving on the
+     * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
      * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
@@ -858,19 +877,17 @@
      * the previous one has not been used. Application is responsible for cleaning up unused files
      * after {@link #stop} is called.
      *
-     * @param  path The pathname to use.
+     * @param  file The file to use.
      * @throws IllegalStateException if it is called before prepare().
      * @throws IOException if setNextOutputFile fails otherwise.
      */
-    public void setNextOutputFile(String path) throws IllegalStateException, IOException
+    public void setNextOutputFile(File file) throws IllegalStateException, IOException
     {
-        if (path != null) {
-            RandomAccessFile file = new RandomAccessFile(path, "rws");
-            try {
-                _setNextOutputFile(file.getFD());
-            } finally {
-                file.close();
-            }
+        RandomAccessFile f = new RandomAccessFile(file, "rws");
+        try {
+            _setNextOutputFile(f.getFD());
+        } finally {
+            f.close();
         }
     }
 
@@ -899,6 +916,13 @@
             }
         } else if (mFd != null) {
             _setOutputFile(mFd);
+        } else if (mFile != null) {
+            RandomAccessFile file = new RandomAccessFile(mFile, "rws");
+            try {
+                _setOutputFile(file.getFD());
+            } finally {
+                file.close();
+            }
         } else {
             throw new IOException("No valid output file");
         }
@@ -1267,23 +1291,142 @@
     /**
      *  Return Metrics data about the current Mediarecorder instance.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media being generated by this instance of
      * MediaRecorder.
-     * The attributes are descibed in {@link MediaMetricsSet.MediaRecorder}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     @Override
     protected void finalize() { native_finalize(); }
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the audio bitrate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+
+        /**
+         * Key to extract the number of audio channels
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+
+        /**
+         * Key to extract the audio samplerate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+
+        /**
+         * Key to extract the audio timescale
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+
+        /**
+         * Key to extract the video capture frame rate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is a double.
+         */
+        public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+
+        /**
+         * Key to extract the video capture framerate enable value
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+
+        /**
+         * Key to extract the intended playback frame rate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String FRAMERATE = "android.media.mediarecorder.frame-rate";
+
+        /**
+         * Key to extract the height (in pixels) of the captured video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String HEIGHT = "android.media.mediarecorder.height";
+
+        /**
+         * Key to extract the recorded movies time units
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         * A value of 1000 indicates that the movie's timing is in milliseconds.
+         */
+        public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+
+        /**
+         * Key to extract the rotation (in degrees) to properly orient the video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String ROTATION = "android.media.mediarecorder.rotation";
+
+        /**
+         * Key to extract the video bitrate from being used
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+
+        /**
+         * Key to extract the value for how often video iframes are generated
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+
+        /**
+         * Key to extract the video encoding level
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+
+        /**
+         * Key to extract the video encoding profile
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+
+        /**
+         * Key to extract the recorded video time units
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         * A value of 1000 indicates that the video's timing is in milliseconds.
+         */
+        public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+
+        /**
+         * Key to extract the width (in pixels) of the captured video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String WIDTH = "android.media.mediarecorder.width";
+
+    }
 }
 
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a8dd313..2178607 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2002,7 +2002,7 @@
     { "getName", "()Ljava/lang/String;",
       (void *)android_media_MediaCodec_getName },
 
-    { "native_getMetrics", "()Landroid/os/Bundle;",
+    { "native_getMetrics", "()Landroid/os/PersistableBundle;",
       (void *)android_media_MediaCodec_native_getMetrics},
 
     { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index c2cfed9..9e5d3d1 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -905,7 +905,7 @@
     { "hasCacheReachedEndOfStream", "()Z",
       (void *)android_media_MediaExtractor_hasCacheReachedEOS },
 
-    {"native_getMetrics",          "()Landroid/os/Bundle;",
+    {"native_getMetrics",          "()Landroid/os/PersistableBundle;",
       (void *)android_media_MediaExtractor_native_getMetrics},
 };
 
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index fb606ba..8979cec 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -24,15 +24,12 @@
 
 namespace android {
 
-// place the attributes into a java Bundle object
-// decide whether this is appropriately scoped here.
-// if we do it somewhere else, we have to figure a "give me all the attrs"
-// access to the inside of MediaAnalyticsItem
+// place the attributes into a java PersistableBundle object
 jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
 
-    jclass clazzBundle = env->FindClass("android/os/Bundle");
+    jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
     if (clazzBundle==NULL) {
-        ALOGD("can't find android/os/Bundle");
+        ALOGD("can't find android/os/PersistableBundle");
         return NULL;
     }
     // sometimes the caller provides one for us to fill
@@ -58,7 +55,7 @@
     // -- get name, get type, get value
     // -- insert appropriately into the bundle
     for (size_t i = 0 ; i < item->mPropCount; i++ ) {
-	    MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+            MediaAnalyticsItem::Prop *prop = &item->mProps[i];
             // build the key parameter from prop->mName
             jstring keyName = env->NewStringUTF(prop->mName);
             // invoke the appropriate method to insert
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 1b52cf5..2fc4afd 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1393,7 +1393,7 @@
     {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
-    {"native_getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaPlayer_native_getMetrics},
+    {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer_native_getMetrics},
     {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
     {"setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer_setSyncParams},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 7a63e00..2c1e834 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -688,7 +688,7 @@
     {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
     {"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
 
-    {"native_getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaRecorder_native_getMetrics},
+    {"native_getMetrics",    "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics},
 };
 
 // This function only registers the native methods, and is called from
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
index 444705c..ece700d 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
@@ -100,8 +100,8 @@
                 int newState) {
             String intentAction;
             if (newState == BluetoothProfile.STATE_CONNECTED) {
-                Log.i(TAG, "Connected to GATT server.");
-                Log.i(TAG, "Attempting to start service discovery:" +
+                Log.d(TAG, "Connected to GATT server.");
+                Log.d(TAG, "Attempting to start service discovery:" +
                         mBluetoothGatt.discoverServices());
             } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                 Log.i(TAG, "Disconnected from GATT server.");
@@ -112,24 +112,24 @@
         @Override
         public void onServicesDiscovered(BluetoothGatt gatt, int status) {
             if (status == BluetoothGatt.GATT_SUCCESS) {
-                List<BluetoothGattService> services = mBluetoothGatt.getServices();
-                for (BluetoothGattService service : services) {
-                    if (MIDI_SERVICE.equals(service.getUuid())) {
-                        Log.d(TAG, "found MIDI_SERVICE");
-                        List<BluetoothGattCharacteristic> characteristics
-                            = service.getCharacteristics();
-                        for (BluetoothGattCharacteristic characteristic : characteristics) {
-                            if (MIDI_CHARACTERISTIC.equals(characteristic.getUuid())) {
-                                Log.d(TAG, "found MIDI_CHARACTERISTIC");
-                                mCharacteristic = characteristic;
+                BluetoothGattService service = gatt.getService(MIDI_SERVICE);
+                if (service != null) {
+                    Log.d(TAG, "found MIDI_SERVICE");
+                    BluetoothGattCharacteristic characteristic
+                            = service.getCharacteristic(MIDI_CHARACTERISTIC);
+                    if (characteristic != null) {
+                        Log.d(TAG, "found MIDI_CHARACTERISTIC");
+                        mCharacteristic = characteristic;
 
-                                // Specification says to read the characteristic first and then
-                                // switch to receiving notifications
-                                mBluetoothGatt.readCharacteristic(characteristic);
-                                break;
-                            }
-                        }
-                        break;
+                        // Request a lower Connection Interval for better latency.
+                        boolean result = gatt.requestConnectionPriority(
+                                BluetoothGatt.CONNECTION_PRIORITY_HIGH);
+                        Log.d(TAG, "requestConnectionPriority(CONNECTION_PRIORITY_HIGH):"
+                            + result);
+
+                        // Specification says to read the characteristic first and then
+                        // switch to receiving notifications
+                        mBluetoothGatt.readCharacteristic(characteristic);
                     }
                 }
             } else {
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index 55d000c..e399fb1 100644
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.defcontainer" coreApp="true">
+    <uses-permission android:name="android.permission.ALLOCATE_AGGRESSIVE"/>
     <uses-permission android:name="android.permission.ASEC_ACCESS"/>
     <uses-permission android:name="android.permission.ASEC_CREATE"/>
     <uses-permission android:name="android.permission.ASEC_DESTROY"/>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 37a68e0..9347877 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.res.ObbInfo;
 import android.content.res.ObbScanner;
+import android.os.Binder;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
@@ -179,6 +180,15 @@
                 return ret;
             }
 
+            final int recommendedInstallLocation;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
+                        pkg.packageName, pkg.installLocation, sizeBytes, flags);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
             ret.packageName = pkg.packageName;
             ret.splitNames = pkg.splitNames;
             ret.versionCode = pkg.versionCode;
@@ -186,8 +196,7 @@
             ret.splitRevisionCodes = pkg.splitRevisionCodes;
             ret.installLocation = pkg.installLocation;
             ret.verifiers = pkg.verifiers;
-            ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
-                    pkg.packageName, pkg.installLocation, sizeBytes, flags);
+            ret.recommendedInstallLocation = recommendedInstallLocation;
             ret.multiArch = pkg.multiArch;
 
             return ret;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index f277165..314791e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -234,10 +234,19 @@
     }
 
     /**
-     * Forces an update of the wifi networks when not scanning.
+     * Synchronously update the list of access points with the latest information.
      */
     public void forceUpdate() {
+        mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+
+        mLastInfo = mWifiManager.getConnectionInfo();
+        mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
         updateAccessPoints();
+
+        // Synchronously copy access points
+        mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED);
+        mMainHandler.handleMessage(
+                Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED));
     }
 
     /**
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index f9e695d..b938fe2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.atLeast;
@@ -33,12 +32,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.Network;
 import android.net.NetworkBadging;
 import android.net.NetworkInfo;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
-import android.net.ScoredNetwork;
 import android.net.RssiCurve;
+import android.net.ScoredNetwork;
 import android.net.WifiKey;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
@@ -47,10 +47,10 @@
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.WifiSsid;
 import android.os.Bundle;
-import android.os.SystemClock;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -62,8 +62,8 @@
 import org.junit.runner.RunWith;
 
 import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
 import org.mockito.Captor;
+import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
@@ -666,4 +666,29 @@
         verify(mockWifiManager, atLeast(2)).getConnectionInfo();
         assertThat(tracker.getAccessPoints().get(0).getRssi()).isEqualTo(newRssi);
     }
+
+    @Test
+    public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception {
+        when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
+
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = SSID_1;
+        configuration.BSSID = BSSID_1;
+        configuration.networkId = CONNECTED_NETWORK_ID;
+        when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+        NetworkInfo networkInfo = new NetworkInfo(
+                ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
+        when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo);
+
+
+        WifiTracker tracker = createMockedWifiTracker();
+        startTracking(tracker);
+        tracker.forceUpdate();
+
+        verify(mockWifiListener).onAccessPointsChanged();
+        assertThat(tracker.getAccessPoints().size()).isEqualTo(2);
+        assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml
index 3f0caab..0c4fd23 100644
--- a/packages/SystemUI/res/values/styles_tv.xml
+++ b/packages/SystemUI/res/values/styles_tv.xml
@@ -21,5 +21,6 @@
     <style name="PipTheme" parent="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:backgroundDimEnabled">false</item>
+        <item name="android:windowDisablePreview">true</item>
      </style>
 </resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f8d1bfb..7a6ac57 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -165,11 +165,6 @@
     private int mPhoneState;
     private boolean mKeyguardIsVisible;
 
-    /**
-     * If true, fingerprint was already authenticated and we don't need to start listening again
-     * until the Keyguard has been dismissed.
-     */
-    private boolean mFingerprintAlreadyAuthenticated;
     private boolean mGoingToSleep;
     private boolean mBouncer;
     private boolean mBootCompleted;
@@ -409,11 +404,8 @@
     private void onFingerprintAuthenticated(int userId) {
         Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
         mUserFingerprintAuthenticated.put(userId, true);
-
-        // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
-        // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
-        // fully gone.
-        mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
+        // Don't send cancel if authentication succeeds
+        mFingerprintCancelSignal = null;
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -922,7 +914,6 @@
             }
         }
         mGoingToSleep = true;
-        mFingerprintAlreadyAuthenticated = false;
         updateFingerprintListeningState();
     }
 
@@ -1092,8 +1083,7 @@
 
     private boolean shouldListenForFingerprint() {
         return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep)
-                && !mSwitchingUser && !mFingerprintAlreadyAuthenticated
-                && !isFingerprintDisabled(getCurrentUser());
+                && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser());
     }
 
     private void startListeningForFingerprint() {
@@ -1416,9 +1406,6 @@
                 cb.onKeyguardVisibilityChangedRaw(showing);
             }
         }
-        if (!showing) {
-            mFingerprintAlreadyAuthenticated = false;
-        }
         updateFingerprintListeningState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index f3fb1ef..ec56e15 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -33,6 +33,8 @@
     boolean isPulsingBlocked();
 
     void startPendingIntentDismissingKeyguard(PendingIntent intent);
+    void abortPulsing();
+    void extendPulse();
 
     interface Callback {
         default void onNotificationHeadsUp() {}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index f27521e..1cc5fb9 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -58,12 +58,15 @@
         /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
         DOZE_PULSE_DONE,
         /** Doze is done. DozeService is finished. */
-        FINISH;
+        FINISH,
+        /** AOD, but the display is temporarily off. */
+        DOZE_AOD_PAUSED;
 
         boolean canPulse() {
             switch (this) {
                 case DOZE:
                 case DOZE_AOD:
+                case DOZE_AOD_PAUSED:
                     return true;
                 default:
                     return false;
@@ -85,6 +88,7 @@
                 case UNINITIALIZED:
                 case INITIALIZED:
                 case DOZE:
+                case DOZE_AOD_PAUSED:
                     return Display.STATE_OFF;
                 case DOZE_PULSING:
                 case DOZE_AOD:
@@ -241,6 +245,11 @@
         if (mState == State.FINISH) {
             return State.FINISH;
         }
+        if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD || mState == State.DOZE)
+                && requestedState == State.DOZE_PULSE_DONE) {
+            Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
+            return mState;
+        }
         if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
             Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
             return mState;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 2ac0657..73f5222 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -22,6 +22,8 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.TriggerEvent;
 import android.hardware.TriggerEventListener;
@@ -40,6 +42,7 @@
 
 import java.io.PrintWriter;
 import java.util.List;
+import java.util.function.Consumer;
 
 public class DozeSensors {
 
@@ -55,18 +58,22 @@
     private final DozeParameters mDozeParameters;
     private final AmbientDisplayConfiguration mConfig;
     private final WakeLock mWakeLock;
+    private final Consumer<Boolean> mProxCallback;
     private final Callback mCallback;
 
     private final Handler mHandler = new Handler();
+    private final ProxSensor mProxSensor;
 
 
     public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
-            AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback) {
+            AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
+            Consumer<Boolean> proxCallback) {
         mContext = context;
         mSensorManager = sensorManager;
         mDozeParameters = dozeParameters;
         mConfig = config;
         mWakeLock = wakeLock;
+        mProxCallback = proxCallback;
         mResolver = mContext.getContentResolver();
 
         mSensors = new TriggerSensor[] {
@@ -86,6 +93,8 @@
                         true /* configured */,
                         DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
         };
+
+        mProxSensor = new ProxSensor();
         mCallback = callback;
     }
 
@@ -129,6 +138,10 @@
         }
     }
 
+    public void setProxListening(boolean listen) {
+        mProxSensor.setRegistered(listen);
+    }
+
     private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
@@ -152,6 +165,43 @@
         }
     }
 
+    private class ProxSensor implements SensorEventListener {
+
+        boolean mRegistered;
+        Boolean mCurrentlyFar;
+
+        void setRegistered(boolean register) {
+            if (mRegistered == register) {
+                // Send an update even if we don't re-register.
+                mHandler.post(() -> {
+                    if (mCurrentlyFar != null) {
+                        mProxCallback.accept(mCurrentlyFar);
+                    }
+                });
+                return;
+            }
+            if (register) {
+                mRegistered = mSensorManager.registerListener(this,
+                        mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
+                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+            } else {
+                mSensorManager.unregisterListener(this);
+                mRegistered = false;
+                mCurrentlyFar = null;
+            }
+        }
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
+            mProxCallback.accept(mCurrentlyFar);
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        }
+    }
+
     private class TriggerSensor extends TriggerEventListener {
         final Sensor mSensor;
         final boolean mConfigured;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 1b9bf73..9b3593b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -46,6 +46,7 @@
 public class DozeTriggers implements DozeMachine.Part {
 
     private static final String TAG = "DozeTriggers";
+    private static final boolean DEBUG = DozeService.DEBUG;
 
     /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */
     private static final String PULSE_ACTION = "com.android.systemui.doze.pulse";
@@ -81,7 +82,7 @@
         mWakeLock = wakeLock;
         mAllowPulseTriggers = allowPulseTriggers;
         mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
-                wakeLock, this::onSensor);
+                wakeLock, this::onSensor, this::onProximityFar);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
     }
 
@@ -113,6 +114,22 @@
         }
     }
 
+    private void onProximityFar(boolean far) {
+        final boolean near = !far;
+        DozeMachine.State state = mMachine.getState();
+        if (near && state == DozeMachine.State.DOZE_PULSING) {
+            if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse");
+            mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
+        }
+        if (far && state == DozeMachine.State.DOZE_AOD_PAUSED) {
+            if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
+            mMachine.requestState(DozeMachine.State.DOZE_AOD);
+        } else if (near && state == DozeMachine.State.DOZE_AOD) {
+            if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
+            mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+        }
+    }
+
     private void onCarMode() {
         mMachine.requestState(DozeMachine.State.FINISH);
     }
@@ -131,15 +148,21 @@
                 break;
             case DOZE:
             case DOZE_AOD:
+            case DOZE_AOD_PAUSED:
+                mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
                 mDozeSensors.setListening(true);
                 if (oldState != DozeMachine.State.INITIALIZED) {
                     mDozeSensors.reregisterAllSensors();
                 }
                 break;
+            case DOZE_PULSING:
+                mDozeSensors.setProxListening(true);
+                break;
             case FINISH:
                 mBroadcastReceiver.unregister(mContext);
                 mDozeHost.removeCallback(mHostCallback);
                 mDozeSensors.setListening(false);
+                mDozeSensors.setProxListening(false);
                 break;
             default:
         }
@@ -156,6 +179,7 @@
 
     private void requestPulse(final int reason, boolean performedProxCheck) {
         Assert.isMainThread();
+        mDozeHost.extendPulse();
         if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
             return;
         }
@@ -286,6 +310,8 @@
     }
 
     private class TriggerReceiver extends BroadcastReceiver {
+        private boolean mRegistered;
+
         @Override
         public void onReceive(Context context, Intent intent) {
             if (PULSE_ACTION.equals(intent.getAction())) {
@@ -301,14 +327,22 @@
         }
 
         public void register(Context context) {
+            if (mRegistered) {
+                return;
+            }
             IntentFilter filter = new IntentFilter(PULSE_ACTION);
             filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
             filter.addAction(Intent.ACTION_USER_SWITCHED);
             context.registerReceiver(this, filter);
+            mRegistered = true;
         }
 
         public void unregister(Context context) {
+            if (!mRegistered) {
+                return;
+            }
             context.unregisterReceiver(this);
+            mRegistered = false;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index f577654..6098a20 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -75,11 +75,14 @@
                 scheduleTimeTick();
                 break;
             case DOZE:
+            case DOZE_AOD_PAUSED:
                 unscheduleTimeTick();
                 break;
             case DOZE_REQUEST_PULSE:
                 pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
                 break;
+            case DOZE_PULSE_DONE:
+                mHost.abortPulsing();
             case INITIALIZED:
                 mHost.startDozing();
                 break;
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 9c4f16b..ac06703 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -195,6 +195,7 @@
 
         updateFromIntent(getIntent());
         setTitle(R.string.pip_menu_title);
+        setDisablePreviewScreenshots(true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index fb8574d..127296cd 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -37,10 +37,12 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.Choreographer;
 import android.view.animation.Interpolator;
 
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
@@ -72,6 +74,7 @@
 
     private Context mContext;
     private IActivityManager mActivityManager;
+    private SurfaceFlingerVsyncChoreographer mVsyncChoreographer;
     private Handler mHandler;
 
     private PipSnapAlgorithm mSnapAlgorithm;
@@ -96,6 +99,8 @@
         mActivityManager = activityManager;
         mSnapAlgorithm = snapAlgorithm;
         mFlingAnimationUtils = flingAnimationUtils;
+        mVsyncChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, mContext.getDisplay(),
+                Choreographer.getInstance());
         onConfigurationChanged();
     }
 
@@ -394,7 +399,7 @@
      */
     private void resizePipUnchecked(Rect toBounds) {
         if (!toBounds.equals(mBounds)) {
-            mHandler.post(() -> {
+            mVsyncChoreographer.scheduleAtSfVsync(() -> {
                 try {
                     mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
                     mBounds.set(toBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index be16266..dd99749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -23,6 +23,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.widget.LinearLayout;
 
 import com.android.systemui.Dependency;
@@ -36,6 +37,7 @@
 import com.android.systemui.statusbar.policy.EncryptionHelper;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 /**
  * Contains the collapsed status bar and handles hiding/showing based on disable flags
@@ -56,6 +58,13 @@
     private DarkIconManager mDarkIconManager;
     private SignalClusterView mSignalClusterView;
 
+    private SignalCallback mSignalCallback = new SignalCallback() {
+        @Override
+        public void setIsAirplaneMode(NetworkController.IconState icon) {
+            mStatusBarComponent.recomputeDisableFlags(true /* animate */);
+        }
+    };
+
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -84,6 +93,7 @@
         Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
         // Default to showing until we know otherwise.
         showSystemIconArea(false);
+        initEmergencyCryptkeeperText();
     }
 
     @Override
@@ -109,6 +119,9 @@
         super.onDestroyView();
         Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
         Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+        if (mNetworkController.hasEmergencyCryptKeeperText()) {
+            mNetworkController.removeCallback(mSignalCallback);
+        }
     }
 
     public void initNotificationIconArea(NotificationIconAreaController
@@ -233,4 +246,17 @@
                     .start();
         }
     }
+
+    private void initEmergencyCryptkeeperText() {
+        View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
+        if (mNetworkController.hasEmergencyCryptKeeperText()) {
+            if (emergencyViewStub != null) {
+                ((ViewStub) emergencyViewStub).inflate();
+            }
+            mNetworkController.addCallback(mSignalCallback);
+        } else if (emergencyViewStub != null) {
+            ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
+            parent.removeView(emergencyViewStub);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index c3f8d97..40776ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -158,6 +158,10 @@
         return sPickupSubtypePerformsProxMatcher.isIn(subType);
     }
 
+    public int getPulseVisibleDurationExtended() {
+        return 2 * getPulseVisibleDuration();
+    }
+
 
     /**
      * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index b78f748..c5f23c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -30,6 +30,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.doze.DozeTriggers;
 
 /**
  * Controller which handles all the doze animations of the scrims.
@@ -43,8 +44,6 @@
     private final ScrimController mScrimController;
 
     private final Context mContext;
-    private final View mStackScroller;
-    private final NotificationPanelView mNotificationPanelView;
 
     private boolean mDozing;
     private DozeHost.PulseCallback mPulseCallback;
@@ -53,24 +52,22 @@
     private Animator mBehindAnimator;
     private float mInFrontTarget;
     private float mBehindTarget;
+    private boolean mDozingAborted;
 
-    public DozeScrimController(ScrimController scrimController, Context context,
-            View stackScroller, NotificationPanelView notificationPanelView) {
+    public DozeScrimController(ScrimController scrimController, Context context) {
         mContext = context;
-        mStackScroller = stackScroller;
         mScrimController = scrimController;
         mDozeParameters = new DozeParameters(context);
-        mNotificationPanelView = notificationPanelView;
     }
 
     public void setDozing(boolean dozing, boolean animate) {
         if (mDozing == dozing) return;
         mDozing = dozing;
         if (mDozing) {
+            mDozingAborted = false;
             abortAnimations();
             mScrimController.setDozeBehindAlpha(1f);
             mScrimController.setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? 0f : 1f);
-            mNotificationPanelView.setDark(true);
         } else {
             cancelPulsing();
             if (animate) {
@@ -85,8 +82,6 @@
                 mScrimController.setDozeBehindAlpha(0f);
                 mScrimController.setDozeInFrontAlpha(0f);
             }
-            // TODO: animate
-            mNotificationPanelView.setDark(false);
         }
     }
 
@@ -116,10 +111,19 @@
         cancelPulsing();
         if (mDozing) {
             mScrimController.setDozeBehindAlpha(1f);
-            mScrimController.setDozeInFrontAlpha(1f);
+            mScrimController.setDozeInFrontAlpha(
+                    mDozeParameters.getAlwaysOn() && !mDozingAborted ? 0f : 1f);
         }
     }
 
+    /**
+     * Aborts dozing immediately.
+     */
+    public void abortDoze() {
+        mDozingAborted = true;
+        abortPulsing();
+    }
+
     public void onScreenTurnedOn() {
         if (isPulsing()) {
             final boolean pickupOrDoubleTap = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP
@@ -139,12 +143,17 @@
         return mDozing;
     }
 
+    public void extendPulse() {
+        mHandler.removeCallbacks(mPulseOut);
+    }
+
     private void cancelPulsing() {
         if (DEBUG) Log.d(TAG, "Cancel pulsing");
 
         if (mPulseCallback != null) {
             mHandler.removeCallbacks(mPulseIn);
             mHandler.removeCallbacks(mPulseOut);
+            mHandler.removeCallbacks(mPulseOutExtended);
             pulseFinished();
         }
     }
@@ -271,12 +280,23 @@
             if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
             if (!mDozing) return;
             mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
+            mHandler.postDelayed(mPulseOutExtended,
+                    mDozeParameters.getPulseVisibleDurationExtended());
+        }
+    };
+
+    private final Runnable mPulseOutExtended = new Runnable() {
+        @Override
+        public void run() {
+            mHandler.removeCallbacks(mPulseOut);
+            mPulseOut.run();
         }
     };
 
     private final Runnable mPulseOut = new Runnable() {
         @Override
         public void run() {
+            mHandler.removeCallbacks(mPulseOutExtended);
             if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
             if (!mDozing) return;
             startScrimAnimation(true /* inFront */, mDozeParameters.getAlwaysOn() ? 0 : 1,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 2bb3cbc..9206914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -221,7 +221,7 @@
             case MODE_WAKE_AND_UNLOCK:
                 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
                 mStatusBarWindowManager.setStatusBarFocusable(false);
-                mDozeScrimController.abortPulsing();
+                mDozeScrimController.abortDoze();
                 mKeyguardViewMediator.onWakeAndUnlocking();
                 mScrimController.setWakeAndUnlocking();
                 if (mStatusBar.getNavigationBarView() != null) {
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 d3cb6a4a8..f0d38b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1114,14 +1114,11 @@
         }
         mHeadsUpManager.addListener(mScrimController);
         mStackScroller.setScrimController(mScrimController);
-        mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller,
-                mNotificationPanel);
+        mDozeScrimController = new DozeScrimController(mScrimController, context);
 
         // Other icons
         mVolumeComponent = getComponent(VolumeComponent.class);
 
-        initEmergencyCryptkeeperText();
-
         mKeyguardBottomArea.setStatusBar(this);
         mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
         if (UserManager.get(mContext).isUserSwitcherEnabled()) {
@@ -1231,24 +1228,6 @@
         });
     }
 
-    private void initEmergencyCryptkeeperText() {
-        View emergencyViewStub = mStatusBarWindow.findViewById(R.id.emergency_cryptkeeper_text);
-        if (mNetworkController.hasEmergencyCryptKeeperText()) {
-            if (emergencyViewStub != null) {
-                ((ViewStub) emergencyViewStub).inflate();
-            }
-            mNetworkController.addCallback(new NetworkController.SignalCallback() {
-                @Override
-                public void setIsAirplaneMode(NetworkController.IconState icon) {
-                    recomputeDisableFlags(true /* animate */);
-                }
-            });
-        } else if (emergencyViewStub != null) {
-            ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
-            parent.removeView(emergencyViewStub);
-        }
-    }
-
     /**
      * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
      * background window of the status bar is clicked.
@@ -4332,6 +4311,7 @@
         mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
         mScrimController.setDozing(mDozing);
         mKeyguardIndicationController.setDozing(mDozing);
+        mNotificationPanel.setDark(mDozing);
 
         // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock
         // for pulsing so the Keyguard fade-out animation scrim can take over.
@@ -4958,6 +4938,7 @@
         mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD
                 || mFingerprintUnlockController.getMode()
                         == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+        mStatusBarWindowManager.setDozing(mDozing);
         updateDozingState();
         Trace.endSection();
     }
@@ -5065,6 +5046,16 @@
             StatusBar.this.startPendingIntentDismissingKeyguard(intent);
         }
 
+        @Override
+        public void abortPulsing() {
+            mDozeScrimController.abortPulsing();
+        }
+
+        @Override
+        public void extendPulse() {
+            mDozeScrimController.extendPulse();
+        }
+
     }
 
     // Begin Extra BaseStatusBar methods.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index deb0070..0326e40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -118,7 +118,7 @@
             mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
 
-        if (state.keyguardShowing && !state.backdropShowing) {
+        if (state.keyguardShowing && !state.backdropShowing && !state.dozing) {
             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
         } else {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -357,6 +357,11 @@
         apply(mCurrentState);
     }
 
+    public void setDozing(boolean dozing) {
+        mCurrentState.dozing = dozing;
+        apply(mCurrentState);
+    }
+
     public void setBarHeight(int barHeight) {
         mBarHeight = barHeight;
         apply(mCurrentState);
@@ -404,6 +409,7 @@
 
         boolean remoteInputActive;
         boolean forcePluginOpen;
+        boolean dozing;
 
         private boolean isKeyguardShowingAndNotOccluded() {
             return keyguardShowing && !keyguardOccluded;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1848d4e..1a09d75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -255,6 +255,9 @@
         if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
             mStackScrollLayout.closeControlsIfOutsideTouch(ev);
         }
+        if (mService.isDozing()) {
+            mService.mDozeScrimController.extendPulse();
+        }
 
         return super.dispatchTouchEvent(ev);
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 63bf373..57ef6d0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -48,6 +48,7 @@
 import android.provider.Settings;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
+import android.service.autofill.FillRequest;
 import android.service.autofill.IAutoFillService;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -169,7 +170,8 @@
             structure.sanitizeForParceling(true);
 
             // TODO(b/33197203): Need to pipe the bundle
-            session.mRemoteFillService.onFillRequest(structure, null, session.mFlags);
+            FillRequest request = new FillRequest(structure, null, session.mFlags);
+            session.mRemoteFillService.onFillRequest(request);
         }
     };
 
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index dd520ac..3badcfc 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -20,12 +20,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.assist.AssistStructure;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.ICancellationSignal;
@@ -33,10 +31,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.autofill.AutofillService;
+import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
+import android.service.autofill.SaveRequest;
 import android.text.format.DateUtils;
 import android.util.Slog;
 
@@ -88,7 +88,7 @@
 
     public interface FillServiceCallbacks {
         void onFillRequestSuccess(@Nullable FillResponse response,
-                @NonNull String servicePackageName);
+                @NonNull String servicePackageName, int requestId);
         void onFillRequestFailure(@Nullable CharSequence message,
                 @NonNull String servicePackageName);
         void onSaveRequestSuccess(@NonNull String servicePackageName);
@@ -134,17 +134,16 @@
         mCallbacks.onServiceDied(this);
     }
 
-    public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
-            int flags) {
+    public void onFillRequest(@NonNull FillRequest request) {
         cancelScheduledUnbind();
-        final PendingFillRequest request = new PendingFillRequest(structure, extras, this, flags);
-        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+        final PendingFillRequest pendingRequest = new PendingFillRequest(request, this);
+        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget();
     }
 
-    public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+    public void onSaveRequest(@NonNull SaveRequest request) {
         cancelScheduledUnbind();
-        final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
-        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+        final PendingSaveRequest pendingRequest = new PendingSaveRequest(request, this);
+        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget();
     }
 
     // Note: we are dumping without a lock held so this is a bit racy but
@@ -253,10 +252,11 @@
     }
 
     private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest,
-            FillResponse response) {
+            FillResponse response, int requestId) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName());
+                mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName(),
+                        requestId);
             }
         });
     }
@@ -392,18 +392,13 @@
     private static final class PendingFillRequest extends PendingRequest {
         private final Object mLock = new Object();
         private final WeakReference<RemoteFillService> mWeakService;
-        private final AssistStructure mStructure;
-        private final Bundle mExtras;
+        private final FillRequest mRequest;
         private final IFillCallback mCallback;
         private ICancellationSignal mCancellation;
         private boolean mCancelled;
-        private int mFlags;
 
-        public PendingFillRequest(AssistStructure structure,
-                Bundle extras, RemoteFillService service, int flags) {
-            mStructure = structure;
-            mExtras = extras;
-            mFlags = flags;
+        public PendingFillRequest(FillRequest request, RemoteFillService service) {
+            mRequest = request;
             mWeakService = new WeakReference<>(service);
             mCallback = new IFillCallback.Stub() {
                 @Override
@@ -425,11 +420,11 @@
                 }
 
                 @Override
-                public void onSuccess(FillResponse response) {
+                public void onSuccess(FillResponse response, int requestId) {
                     RemoteFillService remoteService = mWeakService.get();
                     if (remoteService != null) {
                         remoteService.dispatchOnFillRequestSuccess(
-                                PendingFillRequest.this, response);
+                                PendingFillRequest.this, response, requestId);
                     }
                 }
 
@@ -449,8 +444,7 @@
             RemoteFillService remoteService = mWeakService.get();
             if (remoteService != null) {
                 try {
-                    remoteService.mAutoFillService.onFillRequest(mStructure,
-                            mExtras, mCallback, mFlags);
+                    remoteService.mAutoFillService.onFillRequest(mRequest, mCallback);
                 } catch (RemoteException e) {
                     Slog.e(LOG_TAG, "Error calling on fill request", e);
                     cancel();
@@ -481,14 +475,12 @@
 
     private static final class PendingSaveRequest extends PendingRequest {
         private final WeakReference<RemoteFillService> mWeakService;
-        private final AssistStructure mStructure;
-        private final Bundle mExtras;
+        private final SaveRequest mRequest;
         private final ISaveCallback mCallback;
 
-        public PendingSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
+        public PendingSaveRequest(@NonNull SaveRequest request,
                 @NonNull RemoteFillService service) {
-            mStructure = structure;
-            mExtras = extras;
+            mRequest = request;
             mWeakService = new WeakReference<>(service);
             mCallback = new ISaveCallback.Stub() {
                 @Override
@@ -516,7 +508,7 @@
             final RemoteFillService service = mWeakService.get();
             if (service != null) {
                 try {
-                    service.mAutoFillService.onSaveRequest(mStructure, mExtras, mCallback);
+                    service.mAutoFillService.onSaveRequest(mRequest, mCallback);
                 } catch (RemoteException e) {
                     Slog.e(LOG_TAG, "Error calling on save request", e);
                 }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 1a31161..5feb81d 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -44,11 +44,15 @@
 import android.os.RemoteException;
 import android.service.autofill.AutofillService;
 import android.service.autofill.Dataset;
+import android.service.autofill.FillContext;
+import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
+import android.service.autofill.SaveRequest;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
@@ -125,7 +129,7 @@
     RemoteFillService mRemoteFillService;
 
     @GuardedBy("mLock")
-    private ArrayList<FillResponse> mResponses;
+    private SparseArray<FillResponse> mResponses;
 
     /**
      * Response that requires a service authentitcation request.
@@ -156,7 +160,7 @@
      * and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls.
      */
     @GuardedBy("mLock")
-    private Bundle mExtras;
+    private Bundle mClientState;
 
     /**
      * Flags used to start the session.
@@ -222,7 +226,7 @@
     // FillServiceCallbacks
     @Override
     public void onFillRequestSuccess(@Nullable FillResponse response,
-            @NonNull String servicePackageName) {
+            @NonNull String servicePackageName, int requestId) {
         if (response == null) {
             if ((mFlags & FLAG_MANUAL_REQUEST) != 0) {
                 getUiForShowing().showError(R.string.autofill_error_cannot_autofill);
@@ -243,7 +247,7 @@
                 // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
                 mResponseWaitingAuth = response;
             }
-            processResponseLocked(response);
+            processResponseLocked(response, requestId);
         }
 
         final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
@@ -394,12 +398,18 @@
                     AutofillManager.EXTRA_AUTHENTICATION_RESULT);
             if (result instanceof FillResponse) {
                 mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
+                final int requestIndex = mResponses.indexOfValue(mResponseWaitingAuth);
                 mResponseWaitingAuth = null;
-                processResponseLocked((FillResponse) result);
+                if (requestIndex >= 0) {
+                    final int requestId = mResponses.keyAt(requestIndex);
+                    processResponseLocked((FillResponse) result, requestId);
+                } else {
+                    Slog.e(TAG, "Error cannot find id for auth response");
+                }
             } else if (result instanceof Dataset) {
                 final Dataset dataset = (Dataset) result;
                 for (int i = 0; i < mResponses.size(); i++) {
-                    final FillResponse response = mResponses.get(i);
+                    final FillResponse response = mResponses.valueAt(i);
                     final int index = response.getDatasets().indexOf(mDatasetWaitingAuth);
                     if (index >= 0) {
                         response.getDatasets().set(index, dataset);
@@ -440,12 +450,18 @@
             return true;
         }
 
-        final FillResponse response = mResponses.get(mResponses.size() - 1);
+        final int lastResponseIdx = getLastResponseIndex();
+        if (lastResponseIdx < 0) {
+            Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses
+                    + ", mViewStates=" + mViewStates);
+            return true;
+        }
 
+        final FillResponse response = mResponses.valueAt(lastResponseIdx);
         final SaveInfo saveInfo = response.getSaveInfo();
         if (DEBUG) {
-            Slog.d(TAG,
-                    "showSaveLocked(): mResponses=" + mResponses + ", mViewStates=" + mViewStates);
+            Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses
+                    + ", mViewStates=" + mViewStates);
         }
 
         /*
@@ -572,7 +588,15 @@
             mStructure.dump();
         }
 
-        mRemoteFillService.onSaveRequest(mStructure, mExtras);
+        // TODO(b/33197203): Implement partitioning properly
+        final int lastResponseIdx = getLastResponseIndex();
+        final int requestId = mResponses.keyAt(lastResponseIdx);
+        final FillContext fillContext = new FillContext(requestId, mStructure);
+        final ArrayList fillContexts = new ArrayList(1);
+        fillContexts.add(fillContext);
+
+        final SaveRequest saveRequest = new SaveRequest(fillContexts, mClientState);
+        mRemoteFillService.onSaveRequest(saveRequest);
     }
 
     void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
@@ -686,7 +710,9 @@
             overlay.focused = id.equals(viewState.id);
             node.setAutofillOverlay(overlay);
         }
-        mRemoteFillService.onFillRequest(mStructure, mExtras, 0);
+
+        FillRequest request = new FillRequest(mStructure, mClientState, 0);
+        mRemoteFillService.onFillRequest(request);
 
         return newViewState;
     }
@@ -723,17 +749,17 @@
         }
     }
 
-    private void processResponseLocked(FillResponse response) {
+    private void processResponseLocked(FillResponse response, int requestId) {
         if (DEBUG) {
             Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response);
         }
 
         if (mResponses == null) {
-            mResponses = new ArrayList<>(4);
+            mResponses = new SparseArray<>(4);
         }
-        mResponses.add(response);
+        mResponses.put(requestId, response);
         if (response != null) {
-            mExtras = response.getExtras();
+            mClientState = response.getClientState();
         }
 
         setViewStatesLocked(response, ViewState.STATE_FILLABLE);
@@ -884,7 +910,8 @@
             }
         }
         pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
-        pw.print(prefix); pw.print("mExtras: "); pw.println(Helper.bundleToString(mExtras));
+        pw.print(prefix); pw.print("mClientState: "); pw.println(
+                Helper.bundleToString(mClientState));
         mRemoteFillService.dump(prefix, pw);
     }
 
@@ -961,4 +988,20 @@
         destroyLocked();
         mService.removeSessionLocked(id);
     }
+
+    private int getLastResponseIndex() {
+        // The response ids are monotonically increasing so
+        // we just find the largest id which is the last. We
+        // do not rely on the internal ordering in sparse
+        // array to avoid - wow this stopped working!?
+        int lastResponseIdx = -1;
+        int lastResponseId = -1;
+        final int responseCount = mResponses.size();
+        for (int i = 0; i < responseCount; i++) {
+            if (mResponses.keyAt(i) > lastResponseId) {
+                lastResponseIdx = i;
+            }
+        }
+        return lastResponseIdx;
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 4449da9..ab6a3a7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -161,7 +161,8 @@
                     log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
                     hideFillUiUiThread();
                     if (mCallback != null) {
-                        mCallback.authenticate(response.getAuthentication(), response.getExtras());
+                        mCallback.authenticate(response.getAuthentication(),
+                                response.getClientState());
                     }
                 }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 50c0a12..d5adf48 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -55,6 +55,7 @@
 import android.net.Network;
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
+import android.net.MatchAllNetworkSpecifier;
 import android.net.NetworkConfig;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
@@ -89,7 +90,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -203,6 +203,8 @@
     // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
     private final int mReleasePendingIntentDelayMs;
 
+    private MockableSystemProperties mSystemProperties;
+
     private Tethering mTethering;
 
     private final PermissionMonitor mPermissionMonitor;
@@ -675,6 +677,8 @@
             IpConnectivityLog logger) {
         if (DBG) log("ConnectivityService starting up");
 
+        mSystemProperties = getSystemProperties();
+
         mMetricsLog = logger;
         mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
         NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder());
@@ -692,7 +696,7 @@
         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
 
-        mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
+        mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
 
         mContext = checkNotNull(context, "missing Context");
         mNetd = checkNotNull(netManager, "missing INetworkManagementService");
@@ -722,7 +726,7 @@
         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
 
         // TODO: What is the "correct" way to do determine if this is a wifi only device?
-        boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
+        boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
         log("wifiOnly=" + wifiOnly);
         String[] naStrings = context.getResources().getStringArray(
                 com.android.internal.R.array.networkAttributes);
@@ -775,8 +779,8 @@
             }
         }
 
-        mTestMode = SystemProperties.get("cm.test.mode").equals("true")
-                && SystemProperties.get("ro.build.type").equals("eng");
+        mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
+                && mSystemProperties.get("ro.build.type").equals("eng");
 
         mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
                                    IoThread.get().getLooper(), new MockableSystemProperties());
@@ -1732,8 +1736,8 @@
 
     // Overridden for testing purposes to avoid writing to SystemProperties.
     @VisibleForTesting
-    protected int getDefaultTcpRwnd() {
-        return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0);
+    protected MockableSystemProperties getSystemProperties() {
+        return new MockableSystemProperties();
     }
 
     private void updateTcpBufferSizes(NetworkAgentInfo nai) {
@@ -1771,10 +1775,11 @@
         }
 
         Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
-            Settings.Global.TCP_DEFAULT_INIT_RWND, getDefaultTcpRwnd());
+            Settings.Global.TCP_DEFAULT_INIT_RWND,
+                    mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
         final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
         if (rwndValue != 0) {
-            SystemProperties.set(sysctlKey, rwndValue.toString());
+            mSystemProperties.set(sysctlKey, rwndValue.toString());
         }
     }
 
@@ -1798,7 +1803,7 @@
 
     @Override
     public int getRestoreDefaultNetworkDelay(int networkType) {
-        String restoreDefaultNetworkDelayStr = SystemProperties.get(
+        String restoreDefaultNetworkDelayStr = mSystemProperties.get(
                 NETWORK_RESTORE_DELAY_PROP_NAME);
         if(restoreDefaultNetworkDelayStr != null &&
                 restoreDefaultNetworkDelayStr.length() != 0) {
@@ -2965,7 +2970,7 @@
     @Override
     public boolean isTetheringSupported() {
         enforceTetherAccessPermission();
-        int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
+        int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
         boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
@@ -4044,11 +4049,8 @@
             throw new IllegalArgumentException("Bad timeout specified");
         }
 
-        if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER
-                .equals(networkCapabilities.getNetworkSpecifier())) {
-            throw new IllegalArgumentException("Invalid network specifier - must not be '"
-                    + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
-        }
+        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+                networkCapabilities.getNetworkSpecifier());
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
                 nextNetworkRequestId(), type);
@@ -4117,6 +4119,9 @@
         enforceMeteredApnPolicy(networkCapabilities);
         ensureRequestableCapabilities(networkCapabilities);
 
+        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+                networkCapabilities.getNetworkSpecifier());
+
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
         NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation);
@@ -4178,6 +4183,9 @@
             nc.addCapability(NET_CAPABILITY_FOREGROUND);
         }
 
+        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+                networkCapabilities.getNetworkSpecifier());
+
         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
@@ -4195,6 +4203,9 @@
             enforceAccessPermission();
         }
 
+        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
+                networkCapabilities.getNetworkSpecifier());
+
         NetworkRequest networkRequest = new NetworkRequest(
                 new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
@@ -4466,17 +4477,24 @@
         int last = 0;
         for (InetAddress dns : dnses) {
             ++last;
-            String key = "net.dns" + last;
-            String value = dns.getHostAddress();
-            SystemProperties.set(key, value);
+            setNetDnsProperty(last, dns.getHostAddress());
         }
         for (int i = last + 1; i <= mNumDnsEntries; ++i) {
-            String key = "net.dns" + i;
-            SystemProperties.set(key, "");
+            setNetDnsProperty(i, "");
         }
         mNumDnsEntries = last;
     }
 
+    private void setNetDnsProperty(int which, String value) {
+        final String key = "net.dns" + which;
+        // Log and forget errors setting unsupported properties.
+        try {
+            mSystemProperties.set(key, value);
+        } catch (Exception e) {
+            Log.e(TAG, "Error setting unsupported net.dns property: ", e);
+        }
+    }
+
     private String getNetworkPermission(NetworkCapabilities nc) {
         // TODO: make these permission strings AIDL constants instead.
         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2be5313..6b0a73b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23885,6 +23885,15 @@
         }
     }
 
+    @Override
+    public long getActivityStartInitiatedTime(IBinder token) {
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+        if (r != null) {
+            return r.mStartInitiatedTimeMs;
+        }
+        return 0;
+    }
+
     void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
         final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 276b267..17c7dde 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -341,6 +341,12 @@
     private final Rect mBounds = new Rect();
 
     /**
+     * Denotes the timestamp at which this activity start was last initiated in the
+     * {@link SystemClock#uptimeMillis()} time base.
+     */
+    long mStartInitiatedTimeMs;
+
+    /**
      * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
      */
     private final Configuration mTmpConfig1 = new Configuration();
@@ -498,6 +504,8 @@
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(mActivityType));
+        pw.print(prefix); pw.print("mStartInitiatedTimeMs=");
+                TimeUtils.formatDuration(mStartInitiatedTimeMs, now, pw);
         if (requestedVrComponent != null) {
             pw.print(prefix);
             pw.print("requestedVrComponent=");
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 56594d3..8f1c203 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -244,6 +244,7 @@
             ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
             ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
             TaskRecord inTask) {
+        final long activityStartTime = SystemClock.uptimeMillis();
         int err = ActivityManager.START_SUCCESS;
 
         ProcessRecord callerApp = null;
@@ -478,6 +479,7 @@
                 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                 mSupervisor, container, options, sourceRecord);
+        r.mStartInitiatedTimeMs = activityStartTime;
         if (outActivity != null) {
             outActivity[0] = r;
         }
@@ -1029,6 +1031,7 @@
                         // so make sure the task now has the identity of the new intent.
                         top.getTask().setIntent(mStartActivity);
                     }
+                    top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
                     ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                     top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                             mStartActivity.launchedFromPackage);
@@ -1052,6 +1055,7 @@
             setTaskFromIntentActivity(reusedActivity);
 
             if (!mAddingToTask && mReuseTask == null) {
+                reusedActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
                 // We didn't do anything...  but it was needed (a.k.a., client don't use that
                 // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                 resumeTargetStackIfNeeded();
@@ -1084,6 +1088,7 @@
                 || mLaunchSingleTop || mLaunchSingleTask);
         if (dontStart) {
             ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
+            top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
             // For paranoia, make sure we have correctly resumed the top activity.
             topStack.mLastPausedActivity = null;
             if (mDoResume) {
@@ -1664,6 +1669,7 @@
             // desires.
             if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
                     && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
+                intentActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
                 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
                         intentActivity.getTask());
                 if (intentActivity.frontOfTask) {
diff --git a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
index 4f68652..77b86d8 100644
--- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
+++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java
@@ -19,7 +19,20 @@
 import android.os.SystemProperties;
 
 public class MockableSystemProperties {
+
+    public String get(String key) {
+        return SystemProperties.get(key);
+    }
+
+    public int getInt(String key, int def) {
+        return SystemProperties.getInt(key, def);
+    }
+
     public boolean getBoolean(String key, boolean def) {
         return SystemProperties.getBoolean(key, def);
     }
+
+    public void set(String key, String value) {
+        SystemProperties.set(key, value);
+    }
 }
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 552f0d1..fe49813 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -36,6 +36,7 @@
 
     public abstract boolean handleFailedAttempt();
     public abstract void resetFailedAttempts();
+    private boolean mAlreadyCancelled;
 
     public AuthenticationClient(Context context, long halDeviceId, IBinder token,
             IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
@@ -129,6 +130,10 @@
 
     @Override
     public int stop(boolean initiatedByClient) {
+        if (mAlreadyCancelled) {
+            Slog.w(TAG, "stopAuthentication: already cancelled!");
+            return 0;
+        }
         IBiometricsFingerprint daemon = getFingerprintDaemon();
         if (daemon == null) {
             Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
@@ -145,6 +150,7 @@
             Slog.e(TAG, "stopAuthentication failed", e);
             return ERROR_ESRCH;
         }
+        mAlreadyCancelled = true;
         return 0; // success
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index b0d8adc..2f82915 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -23,6 +23,7 @@
 import android.os.UserHandle;
 import android.util.IntArray;
 import android.util.Log;
+import android.util.SparseArray;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -38,7 +39,7 @@
     private static final String TAG = "MediaSessionStack";
 
     /**
-     * Listens the change in the media button session.
+     * Listen the change in the media button session.
      */
     interface OnMediaButtonSessionChangedListener {
         /**
@@ -85,7 +86,12 @@
 
     private MediaSessionRecord mCachedDefault;
     private MediaSessionRecord mCachedVolumeDefault;
-    private ArrayList<MediaSessionRecord> mCachedActiveList;
+
+    /**
+     * Cache the result of the {@link #getActiveSessions} per user.
+     */
+    private final SparseArray<ArrayList<MediaSessionRecord>> mCachedActiveLists =
+            new SparseArray<>();
 
     MediaSessionStack(AudioPlaybackMonitor monitor, OnMediaButtonSessionChangedListener listener) {
         mAudioPlaybackMonitor = monitor;
@@ -99,7 +105,7 @@
      */
     public void addSession(MediaSessionRecord record) {
         mSessions.add(record);
-        clearCache();
+        clearCache(record.getUserId());
 
         // Update the media button session.
         // The added session could be the session from the package with the audio playback.
@@ -119,7 +125,7 @@
             // in the media button session app.
             onMediaSessionChangeInMediaButtonSessionApp();
         }
-        clearCache();
+        clearCache(record.getUserId());
     }
 
     /**
@@ -140,7 +146,7 @@
         if (shouldUpdatePriority(oldState, newState)) {
             mSessions.remove(record);
             mSessions.add(0, record);
-            clearCache();
+            clearCache(record.getUserId());
         } else if (!MediaSession.isActiveState(newState)) {
             // Just clear the volume cache when a state goes inactive
             mCachedVolumeDefault = null;
@@ -163,7 +169,7 @@
     public void onSessionStateChange(MediaSessionRecord record) {
         // For now just clear the cache. Eventually we'll selectively clear
         // depending on what changed.
-        clearCache();
+        clearCache(record.getUserId());
     }
 
     /**
@@ -245,14 +251,17 @@
      * Get the current priority sorted list of active sessions. The most
      * important session is at index 0 and the least important at size - 1.
      *
-     * @param userId The user to check.
+     * @param userId The user to check. It can be {@link UserHandle#USER_ALL} to get all sessions
+     *    for all users in this {@link MediaSessionStack}.
      * @return All the active sessions in priority order.
      */
     public ArrayList<MediaSessionRecord> getActiveSessions(int userId) {
-        if (mCachedActiveList == null) {
-            mCachedActiveList = getPriorityList(true, userId);
+        ArrayList<MediaSessionRecord> cachedActiveList = mCachedActiveLists.get(userId);
+        if (cachedActiveList == null) {
+            cachedActiveList = getPriorityList(true, userId);
+            mCachedActiveLists.put(userId, cachedActiveList);
         }
-        return mCachedActiveList;
+        return cachedActiveList;
     }
 
     /**
@@ -382,9 +391,12 @@
         return false;
     }
 
-    private void clearCache() {
+    private void clearCache(int userId) {
         mCachedDefault = null;
         mCachedVolumeDefault = null;
-        mCachedActiveList = null;
+        mCachedActiveLists.remove(userId);
+        // mCachedActiveLists may also include the list of sessions for UserHandle.USER_ALL,
+        // so they also need to be cleared.
+        mCachedActiveLists.remove(UserHandle.USER_ALL);
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b7d3173..b48fd5c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -172,7 +172,7 @@
             final boolean useDefaultSound = (n.defaults & Notification.DEFAULT_SOUND) != 0;
             if (useDefaultSound) {
                 sound = Settings.System.DEFAULT_NOTIFICATION_URI;
-            } else if (n.sound != null) {
+            } else {
                 sound = n.sound;
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 650d2f6..9040fcf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -23636,4 +23636,10 @@
     public ComponentName getInstantAppResolverSettingsComponent() {
         return mInstantAppResolverSettingsComponent;
     }
+
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        return mInstantAppInstallerActivity == null
+                ? null : mInstantAppInstallerActivity.getComponentName();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 058fdae..1823610 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -125,6 +125,7 @@
 import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.view.IInputMethodClient;
 
@@ -1396,6 +1397,22 @@
         return null;
     }
 
+    @VisibleForTesting
+    int getStackCount() {
+        return mTaskStackContainers.size();
+    }
+
+    @VisibleForTesting
+    int getStaskPosById(int stackId) {
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
+            if (stack.mStackId == stackId) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     @Override
     void onConfigurationChanged(Configuration newParentConfig) {
         super.onConfigurationChanged(newParentConfig);
@@ -3274,8 +3291,9 @@
                     : requestedPosition >= topChildPosition;
             int targetPosition = requestedPosition;
 
-            if (toTop && isStackVisible(PINNED_STACK_ID) && stack.mStackId != PINNED_STACK_ID) {
-                // The pinned stack is always the top most stack (always-on-top) when it is visible.
+            if (toTop && stack.mStackId != PINNED_STACK_ID
+                    && getStackById(PINNED_STACK_ID) != null) {
+                // The pinned stack is always the top most stack (always-on-top) when it is present.
                 TaskStack topStack = mChildren.get(topChildPosition);
                 if (topStack.mStackId != PINNED_STACK_ID) {
                     throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index 6b3271f..122a954 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -20,10 +20,12 @@
 import static com.android.internal.util.CollectionUtils.size;
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
 
 import android.Manifest;
 import android.annotation.CheckResult;
 import android.annotation.Nullable;
+import android.app.PendingIntent;
 import android.companion.AssociationRequest;
 import android.companion.CompanionDeviceManager;
 import android.companion.ICompanionDeviceDiscoveryService;
@@ -47,13 +49,18 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.SettingsStringUtil.ComponentNameSet;
+import android.text.BidiFormatter;
 import android.util.AtomicFile;
 import android.util.ExceptionUtils;
+import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.server.FgThread;
@@ -80,6 +87,7 @@
 //TODO schedule stopScan on activity destroy(except if configuration change)
 //TODO on associate called again after configuration change -> replace old callback with new
 //TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
+//TODO check user-feature present in manifest on API calls
 /** @hide */
 public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
 
@@ -217,6 +225,7 @@
                     a -> a.deviceAddress);
         }
 
+        //TODO also revoke notification access
         @Override
         public void disassociate(String deviceMacAddress, String callingPackage)
                 throws RemoteException {
@@ -237,11 +246,49 @@
 
             checkArgument(getCallingUserId() == userId,
                     "Must be called by either same user or system");
-
             mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
         }
+
+        @Override
+        public PendingIntent requestNotificationAccess(ComponentName component)
+                throws RemoteException {
+            String callingPackage = component.getPackageName();
+            checkCanCallNotificationApi(callingPackage);
+            int userId = getCallingUserId();
+            String packageTitle = BidiFormatter.getInstance().unicodeWrap(
+                    getPackageInfo(callingPackage, userId)
+                            .applicationInfo
+                            .loadSafeLabel(getContext().getPackageManager())
+                            .toString());
+            long identity = Binder.clearCallingIdentity();
+            try {
+                return PendingIntent.getActivity(getContext(),
+                        0 /* request code */,
+                        NotificationAccessConfirmationActivityContract.launcherIntent(
+                                userId, component, packageTitle),
+                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT
+                                | PendingIntent.FLAG_CANCEL_CURRENT);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public boolean hasNotificationAccess(ComponentName component) throws RemoteException {
+            checkCanCallNotificationApi(component.getPackageName());
+            String setting = Settings.Secure.getString(getContext().getContentResolver(),
+                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+            return new ComponentNameSet(setting).contains(component);
+        }
+
+        private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
+            checkCallerIsSystemOr(callingPackage);
+            checkState(!ArrayUtils.isEmpty(readAllAssociations(getCallingUserId(), callingPackage)),
+                    "App must have an association before calling this API");
+        }
     }
 
+
     private int getCallingUserId() {
         return UserHandle.getUserId(Binder.getCallingUid());
     }
@@ -291,6 +338,17 @@
         return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
 
             @Override
+            public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                    throws RemoteException {
+                try {
+                    return super.onTransact(code, data, reply, flags);
+                } catch (Throwable e) {
+                    Slog.e(LOG_TAG, "Error during IPC", e);
+                    throw ExceptionUtils.propagate(e, RemoteException.class);
+                }
+            }
+
+            @Override
             public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
                 updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
                 recordAssociation(packageName, deviceAddress);
@@ -301,7 +359,6 @@
             public void onDeviceSelectionCancel() {
                 cleanup();
             }
-
         };
     }
 
@@ -351,8 +408,13 @@
     }
 
     private void recordAssociation(String priviledgedPackage, String deviceAddress) {
+        if (DEBUG) {
+            Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage
+                    + ", deviceAddress = " + deviceAddress + ")");
+        }
+        int userId = getCallingUserId();
         updateAssociations(associations -> CollectionUtils.add(associations,
-                new Association(getCallingUserId(), deviceAddress, priviledgedPackage)));
+                new Association(userId, deviceAddress, priviledgedPackage)));
     }
 
     private void updateAssociations(Function<List<Association>, List<Association>> update) {
@@ -364,7 +426,7 @@
         final AtomicFile file = getStorageFileForUser(userId);
         synchronized (file) {
             List<Association> associations = readAllAssociations(userId);
-            final ArrayList<Association> old = new ArrayList<>(associations);
+            final List<Association> old = CollectionUtils.copyOf(associations);
             associations = update.apply(associations);
             if (size(old) == size(associations)) return;
 
@@ -394,15 +456,6 @@
 
             });
         }
-
-
-        //TODO Show dialog before recording notification access
-//        final SettingStringHelper setting =
-//                new SettingStringHelper(
-//                        getContext().getContentResolver(),
-//                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-//                        getUserId());
-//        setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
     }
 
     private AtomicFile getStorageFileForUser(int uid) {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 946044d..b2e6ef9 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -124,6 +124,9 @@
                 builder.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
                 channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
+        } else {
+            channel.setSound(null, null);
+            builder.setSound(null, null);
         }
         if (buzzy) {
             if (defaultVibration) {
@@ -206,6 +209,18 @@
     }
 
     @Test
+    public void testSound_noSound_preUpgrade() throws Exception {
+        // pre upgrade, default sound.
+        StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /*defaultLights */);
+
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+        assertEquals(null, record.getSound());
+        assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
+    }
+
+    @Test
     public void testSound_default_upgradeUsesChannel() throws Exception {
         channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
         // post upgrade, default sound.
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 0270bb9..837ce56 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -289,6 +290,24 @@
         verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity);
     }
 
+    /**
+     * This test enforces that the pinned stack is always kept as the top stack.
+     */
+    @Test
+    public void testPinnedStackLocation() {
+        createStackControllerOnStackOnDisplay(PINNED_STACK_ID, sDisplayContent);
+        final int initialStackCount = sDisplayContent.getStackCount();
+        // Ensure that the pinned stack was placed at the end
+        assertEquals(initialStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
+        // By default, this should try to create a new stack on top
+        createTaskStackOnDisplay(sDisplayContent);
+        final int afterStackCount = sDisplayContent.getStackCount();
+        // Make sure the stack count has increased
+        assertEquals(initialStackCount + 1, afterStackCount);
+        // Ensure that the pinned stack is still on top
+        assertEquals(afterStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
+    }
+
     private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
                              int expectedBaseHeight, int expectedBaseDensity) {
         assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 960a2d9..20392e7 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -1126,4 +1126,12 @@
     public ComponentName getInstantAppResolverSettingsComponent() {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c562cb9..6140a896 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,7 +23,12 @@
 import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.NetworkCapabilities.*;
 
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
 
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -33,6 +38,7 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.ConnectivityManager.PacketKeepalive;
@@ -42,6 +48,7 @@
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.MatchAllNetworkSpecifier;
 import android.net.Network;
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
@@ -51,7 +58,9 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
 import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
 import android.net.RouteInfo;
+import android.net.StringNetworkSpecifier;
 import android.net.metrics.IpConnectivityLog;
 import android.net.util.MultinetworkPolicyTracker;
 import android.os.ConditionVariable;
@@ -64,24 +73,32 @@
 import android.os.MessageQueue;
 import android.os.Messenger;
 import android.os.MessageQueue.IdleHandler;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.test.mock.MockContentResolver;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.LogPrinter;
 
 import com.android.internal.util.WakeupMessage;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.connectivity.MockableSystemProperties;
 import com.android.server.connectivity.NetworkAgentInfo;
 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 org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -134,8 +151,19 @@
     private class MockContext extends BroadcastInterceptingContext {
         private final MockContentResolver mContentResolver;
 
+        @Spy private Resources mResources;
+
         MockContext(Context base) {
             super(base);
+
+            mResources = spy(base.getResources());
+            when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)).
+                    thenReturn(new String[] {
+                            "wifi,1,1,1,-1,true",
+                            "mobile,0,0,0,-1,true",
+                            "mobile_mms,2,0,2,60000,true",
+                    });
+
             mContentResolver = new MockContentResolver();
             mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         }
@@ -151,6 +179,11 @@
         public ContentResolver getContentResolver() {
             return mContentResolver;
         }
+
+        @Override
+        public Resources getResources() {
+            return mResources;
+        }
     }
 
     /**
@@ -319,6 +352,11 @@
             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
         }
 
+        public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
+            mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
+            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+        }
+
         public void connectWithoutInternet() {
             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -621,6 +659,7 @@
     private class WrappedConnectivityService extends ConnectivityService {
         public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker;
         private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
+        private MockableSystemProperties mSystemProperties;
 
         public WrappedConnectivityService(Context context, INetworkManagementService netManager,
                 INetworkStatsService statsService, INetworkPolicyManager policyManager,
@@ -630,9 +669,13 @@
         }
 
         @Override
-        protected int getDefaultTcpRwnd() {
-            // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
-            return 0;
+        protected MockableSystemProperties getSystemProperties() {
+            // Minimal approach to overriding system properties: let most calls fall through to real
+            // device values, and only override ones values that are important to this test.
+            mSystemProperties = spy(new MockableSystemProperties());
+            when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0);
+            when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false);
+            return mSystemProperties;
         }
 
         @Override
@@ -805,6 +848,14 @@
         return cv;
     }
 
+    public void testNetworkTypes() {
+        // Ensure that our mocks for the networkAttributes config variable work as expected. If they
+        // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types
+        // will fail. Failing here is much easier to debug.
+        assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
+        assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
+    }
+
     @SmallTest
     public void testLingering() throws Exception {
         verifyNoNetwork();
@@ -1819,34 +1870,130 @@
         captivePortalCallback.assertNoCallback();
     }
 
-    @SmallTest
-    public void testInvalidNetworkSpecifier() {
-        boolean execptionCalled = true;
+    private NetworkRequest.Builder newWifiRequestBuilder() {
+        return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI);
+    }
 
-        try {
-            NetworkRequest.Builder builder = new NetworkRequest.Builder();
-            builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
-            execptionCalled = false;
-        } catch (IllegalArgumentException e) {
-            // do nothing - should get here
+    @SmallTest
+    public void testNetworkSpecifier() {
+        NetworkRequest rEmpty1 = newWifiRequestBuilder().build();
+        NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build();
+        NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build();
+        NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier(
+            (NetworkSpecifier) null).build();
+        NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build();
+        NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier(
+                new StringNetworkSpecifier("bar")).build();
+
+        TestNetworkCallback cEmpty1 = new TestNetworkCallback();
+        TestNetworkCallback cEmpty2 = new TestNetworkCallback();
+        TestNetworkCallback cEmpty3 = new TestNetworkCallback();
+        TestNetworkCallback cEmpty4 = new TestNetworkCallback();
+        TestNetworkCallback cFoo = new TestNetworkCallback();
+        TestNetworkCallback cBar = new TestNetworkCallback();
+        TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] {
+                cEmpty1, cEmpty2, cEmpty3 };
+
+        mCm.registerNetworkCallback(rEmpty1, cEmpty1);
+        mCm.registerNetworkCallback(rEmpty2, cEmpty2);
+        mCm.registerNetworkCallback(rEmpty3, cEmpty3);
+        mCm.registerNetworkCallback(rEmpty4, cEmpty4);
+        mCm.registerNetworkCallback(rFoo, cFoo);
+        mCm.registerNetworkCallback(rBar, cBar);
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+        cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent);
+        cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent);
+        cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent);
+        cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent);
+        assertNoCallbacks(cFoo, cBar);
+
+        mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo"));
+        cFoo.expectAvailableCallbacks(mWiFiNetworkAgent);
+        for (TestNetworkCallback c: emptyCallbacks) {
+            c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+        }
+        cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+        cFoo.assertNoCallback();
+
+        mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar"));
+        cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        cBar.expectAvailableCallbacks(mWiFiNetworkAgent);
+        for (TestNetworkCallback c: emptyCallbacks) {
+            c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+        }
+        cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+        cBar.assertNoCallback();
+
+        mWiFiNetworkAgent.setNetworkSpecifier(null);
+        cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        for (TestNetworkCallback c: emptyCallbacks) {
+            c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
         }
 
-        assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
-                execptionCalled);
+        assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar);
+    }
+
+    @SmallTest
+    public void testInvalidNetworkSpecifier() {
+        try {
+            NetworkRequest.Builder builder = new NetworkRequest.Builder();
+            builder.setNetworkSpecifier(new MatchAllNetworkSpecifier());
+            fail("NetworkRequest builder with MatchAllNetworkSpecifier");
+        } catch (IllegalArgumentException expected) {
+            // expected
+        }
 
         try {
             NetworkCapabilities networkCapabilities = new NetworkCapabilities();
             networkCapabilities.addTransportType(TRANSPORT_WIFI)
-                    .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+                    .setNetworkSpecifier(new MatchAllNetworkSpecifier());
             mService.requestNetwork(networkCapabilities, null, 0, null,
                     ConnectivityManager.TYPE_WIFI);
-            execptionCalled = false;
-        } catch (IllegalArgumentException e) {
-            // do nothing - should get here
+            fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier");
+        } catch (IllegalArgumentException expected) {
+            // expected
         }
 
-        assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
-                execptionCalled);
+        class NonParcelableSpecifier extends NetworkSpecifier {
+            public boolean satisfiedBy(NetworkSpecifier other) { return false; }
+        };
+        class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable {
+            @Override public int describeContents() { return 0; }
+            @Override public void writeToParcel(Parcel p, int flags) {}
+        }
+        NetworkRequest.Builder builder;
+
+        builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
+        try {
+            builder.setNetworkSpecifier(new NonParcelableSpecifier());
+            Parcel parcelW = Parcel.obtain();
+            builder.build().writeToParcel(parcelW, 0);
+            fail("Parceling a non-parcelable specifier did not throw an exception");
+        } catch (Exception e) {
+            // expected
+        }
+
+        builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET);
+        builder.setNetworkSpecifier(new ParcelableSpecifier());
+        NetworkRequest nr = builder.build();
+        assertNotNull(nr);
+
+        try {
+            Parcel parcelW = Parcel.obtain();
+            nr.writeToParcel(parcelW, 0);
+            byte[] bytes = parcelW.marshall();
+            parcelW.recycle();
+
+            Parcel parcelR = Parcel.obtain();
+            parcelR.unmarshall(bytes, 0, bytes.length);
+            parcelR.setDataPosition(0);
+            NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR);
+            fail("Unparceling a non-framework NetworkSpecifier did not throw an exception");
+        } catch (Exception e) {
+            // expected
+        }
     }
 
     @SmallTest
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 5a239e1..ad26bc8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -923,4 +923,9 @@
     public ComponentName getInstantAppResolverSettingsComponent() {
         return null;
     }
+
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        return null;
+    }
 }