Merge changes I3fd28e69,If43820b6

* changes:
  Lock work tasks from SystemUI instead of ActivityStarter
  Bounce work challenge through a WorkLockActivity
diff --git a/Android.mk b/Android.mk
index 2ea22f3..8e8b95a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -82,7 +82,6 @@
 	core/java/android/app/IBackupAgent.aidl \
 	core/java/android/app/IEphemeralResolver.aidl \
 	core/java/android/app/IInstrumentationWatcher.aidl \
-	core/java/android/app/IOnNotificationChannelCreatedListener.aidl \
 	core/java/android/app/INotificationManager.aidl \
 	core/java/android/app/IProcessObserver.aidl \
 	core/java/android/app/ISearchManager.aidl \
@@ -263,8 +262,9 @@
 	core/java/android/os/storage/IObbActionListener.aidl \
 	core/java/android/security/IKeystoreService.aidl \
 	core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
-	core/java/android/service/autofill/IAutoFillCallback.aidl \
+	core/java/android/service/autofill/IAutoFillAppCallback.aidl \
 	core/java/android/service/autofill/IAutoFillManagerService.aidl \
+	core/java/android/service/autofill/IAutoFillServerCallback.aidl \
 	core/java/android/service/autofill/IAutoFillService.aidl \
 	core/java/android/service/carrier/ICarrierService.aidl \
 	core/java/android/service/carrier/ICarrierMessagingCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index 52135ed..9f6d358 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5413,7 +5413,8 @@
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
-    method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
+    method public void createNotificationChannel(android.app.NotificationChannel);
+    method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
     method public void deleteNotificationChannel(java.lang.String);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5447,10 +5448,6 @@
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
-    method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
-  }
-
   public static class NotificationManager.Policy implements android.os.Parcelable {
     ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
@@ -6371,7 +6368,8 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
-    method public int getAutoFillId();
+    method public android.view.autofill.AutoFillId getAutoFillId();
+    method public android.view.autofill.AutoFillType getAutoFillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -6787,6 +6785,7 @@
     method protected android.view.View getErrorView();
     method protected void prepareView(android.view.View);
     method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
+    method public void setAsyncExecutor(java.util.concurrent.Executor);
     method public void updateAppWidget(android.widget.RemoteViews);
     method public void updateAppWidgetOptions(android.os.Bundle);
     method public void updateAppWidgetSize(android.os.Bundle, int, int, int, int);
@@ -24002,11 +24001,8 @@
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
-    method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
     method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
-    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
-    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
     method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     method public void unregisterNetworkCallback(android.app.PendingIntent);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
@@ -28583,7 +28579,7 @@
     method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
     method public void surfaceCreated(android.view.SurfaceHolder);
     method public void surfaceDestroyed(android.view.SurfaceHolder);
-    method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public deprecated void surfaceRedrawNeeded(android.view.SurfaceHolder);
     field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
     field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
     field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -30936,6 +30932,7 @@
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
     field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
     field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+    field public static final java.lang.String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
     field public static final java.lang.String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
     field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "android.all";
     field public static final java.lang.String ALARM_SEARCH_MODE_LABEL = "android.label";
@@ -35044,26 +35041,19 @@
     method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
     method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
+    field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
+    field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
   }
 
   public final class FillCallback {
     method public void onFailure(java.lang.CharSequence);
-    method public void onSuccess(android.service.autofill.FillCallback.FillData);
-  }
-
-  public static final class FillCallback.FillData {
-  }
-
-  public static class FillCallback.FillData.Builder {
-    ctor public FillCallback.FillData.Builder();
-    method public android.service.autofill.FillCallback.FillData build();
-    method public android.service.autofill.FillCallback.FillData.Builder setTextField(int, java.lang.String);
+    method public void onSuccess(android.view.autofill.FillResponse);
   }
 
   public final class SaveCallback {
     method public void onFailure(java.lang.CharSequence);
-    method public void onSuccess(int[]);
+    method public void onSuccess(android.view.autofill.AutoFillId[]);
   }
 
 }
@@ -36728,6 +36718,7 @@
     method public void unhold();
     method public void unregisterCallback(android.telecom.Call.Callback);
     field public static final java.lang.String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+    field public static final java.lang.String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_CONNECTING = 9; // 0x9
     field public static final int STATE_DIALING = 1; // 0x1
@@ -39461,6 +39452,7 @@
     method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
     method public android.text.StaticLayout.Builder setIncludePad(boolean);
     method public android.text.StaticLayout.Builder setIndents(int[], int[]);
+    method public android.text.StaticLayout.Builder setJustify(boolean);
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -43069,6 +43061,7 @@
 
   public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback {
     method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable);
   }
 
   public class SurfaceView extends android.view.View {
@@ -43149,6 +43142,7 @@
     method public void addTouchables(java.util.ArrayList<android.view.View>);
     method public android.view.ViewPropertyAnimator animate();
     method public void announceForAccessibility(java.lang.CharSequence);
+    method public void autoFill(android.view.autofill.AutoFillValue);
     method protected boolean awakenScrollBars();
     method protected boolean awakenScrollBars(int);
     method protected boolean awakenScrollBars(int, boolean);
@@ -43200,8 +43194,8 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public deprecated void dispatchProvideStructure(android.view.ViewStructure);
-    method public void dispatchProvideStructure(android.view.ViewStructure, int);
+    method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
+    method public void dispatchProvideStructure(android.view.ViewStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -43236,6 +43230,8 @@
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
+    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(android.view.autofill.VirtualViewDelegate.Callback);
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -43472,10 +43468,10 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public deprecated void onProvideStructure(android.view.ViewStructure);
-    method public void onProvideStructure(android.view.ViewStructure, int);
-    method public deprecated void onProvideVirtualStructure(android.view.ViewStructure);
-    method public void onProvideVirtualStructure(android.view.ViewStructure, int);
+    method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
+    method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+    method public void onProvideStructure(android.view.ViewStructure);
+    method public void onProvideVirtualStructure(android.view.ViewStructure);
     method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
@@ -43682,8 +43678,8 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
-    field public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 2; // 0x2
-    field public static final int ASSIST_FLAG_SANITIZED_TEXT = 1; // 0x1
+    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 1; // 0x1
+    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 2; // 0x2
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -44313,6 +44309,7 @@
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewStructure asyncNewChild(int);
+    method public abstract android.view.ViewStructure asyncNewChild(int, int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -44321,9 +44318,11 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
+    method public abstract android.view.ViewStructure newChild(int, int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
+    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -45544,6 +45543,80 @@
 
 }
 
+package android.view.autofill {
+
+  public final class AutoFillId implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillId> CREATOR;
+  }
+
+  public final class AutoFillType implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.view.autofill.AutoFillType forList();
+    method public static android.view.autofill.AutoFillType forText(int);
+    method public static android.view.autofill.AutoFillType forToggle();
+    method public int getSubType();
+    method public boolean isList();
+    method public boolean isText();
+    method public boolean isToggle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillType> CREATOR;
+  }
+
+  public final class AutoFillValue implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.view.autofill.AutoFillValue forList(int);
+    method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
+    method public static android.view.autofill.AutoFillValue forToggle(boolean);
+    method public int getListValue();
+    method public java.lang.CharSequence getTextValue();
+    method public boolean getToggleValue();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillValue> CREATOR;
+  }
+
+  public final class Dataset implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.Dataset> CREATOR;
+  }
+
+  public static final class Dataset.Builder {
+    ctor public Dataset.Builder(java.lang.CharSequence);
+    method public android.view.autofill.Dataset build();
+    method public android.view.autofill.Dataset.Builder setExtras(android.os.Bundle);
+    method public android.view.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
+  }
+
+  public final class FillResponse implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.FillResponse> CREATOR;
+  }
+
+  public static final class FillResponse.Builder {
+    ctor public FillResponse.Builder();
+    method public android.view.autofill.FillResponse.Builder addDataset(android.view.autofill.Dataset);
+    method public android.view.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
+    method public android.view.autofill.FillResponse build();
+    method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+  }
+
+  public abstract class VirtualViewDelegate {
+    ctor public VirtualViewDelegate();
+    method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
+  }
+
+  public static abstract class VirtualViewDelegate.Callback {
+    ctor public VirtualViewDelegate.Callback();
+    method public void onFocusChanged(int, boolean);
+    method public void onNodeRemoved(int...);
+    method public void onValueChanged(int);
+  }
+
+}
+
 package android.view.inputmethod {
 
   public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -48989,6 +49062,7 @@
     method public boolean getIncludeFontPadding();
     method public android.os.Bundle getInputExtras(boolean);
     method public int getInputType();
+    method public boolean getJustify();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
@@ -49097,6 +49171,7 @@
     method public void setIncludeFontPadding(boolean);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
+    method public void setJustify(boolean);
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
diff --git a/api/removed.txt b/api/removed.txt
index d7a8bce..ab22b6e 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -126,6 +126,12 @@
 
 package android.net {
 
+  public class ConnectivityManager {
+    method public deprecated boolean requestRouteToHost(int, int);
+    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
+    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
+  }
+
   public abstract class PskKeyManager {
     ctor public PskKeyManager();
     field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
diff --git a/api/system-current.txt b/api/system-current.txt
index d06a8ac..4c9cada 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5586,7 +5586,8 @@
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
-    method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
+    method public void createNotificationChannel(android.app.NotificationChannel);
+    method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
     method public void deleteNotificationChannel(java.lang.String);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5620,10 +5621,6 @@
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
-    method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
-  }
-
   public static class NotificationManager.Policy implements android.os.Parcelable {
     ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
@@ -6574,7 +6571,8 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
-    method public int getAutoFillId();
+    method public android.view.autofill.AutoFillId getAutoFillId();
+    method public android.view.autofill.AutoFillType getAutoFillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -7101,6 +7099,7 @@
     method protected android.view.View getErrorView();
     method protected void prepareView(android.view.View);
     method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
+    method public void setAsyncExecutor(java.util.concurrent.Executor);
     method public void updateAppWidget(android.widget.RemoteViews);
     method public void updateAppWidgetOptions(android.os.Bundle);
     method public void updateAppWidgetSize(android.os.Bundle, int, int, int, int);
@@ -25794,14 +25793,11 @@
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
-    method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
     method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
     method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
     method public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
-    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
     method public void stopTethering(int);
-    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
     method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     method public void unregisterNetworkCallback(android.app.PendingIntent);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
@@ -31147,7 +31143,7 @@
     method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
     method public void surfaceCreated(android.view.SurfaceHolder);
     method public void surfaceDestroyed(android.view.SurfaceHolder);
-    method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public deprecated void surfaceRedrawNeeded(android.view.SurfaceHolder);
     field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
     field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
     field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -33656,6 +33652,7 @@
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
     field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
     field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+    field public static final java.lang.String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
     field public static final java.lang.String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
     field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "android.all";
     field public static final java.lang.String ALARM_SEARCH_MODE_LABEL = "android.label";
@@ -37907,26 +37904,19 @@
     method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
     method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
+    field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
+    field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
   }
 
   public final class FillCallback {
     method public void onFailure(java.lang.CharSequence);
-    method public void onSuccess(android.service.autofill.FillCallback.FillData);
-  }
-
-  public static final class FillCallback.FillData {
-  }
-
-  public static class FillCallback.FillData.Builder {
-    ctor public FillCallback.FillData.Builder();
-    method public android.service.autofill.FillCallback.FillData build();
-    method public android.service.autofill.FillCallback.FillData.Builder setTextField(int, java.lang.String);
+    method public void onSuccess(android.view.autofill.FillResponse);
   }
 
   public final class SaveCallback {
     method public void onFailure(java.lang.CharSequence);
-    method public void onSuccess(int[]);
+    method public void onSuccess(android.view.autofill.AutoFillId[]);
   }
 
 }
@@ -39662,6 +39652,7 @@
     method public void unhold();
     method public void unregisterCallback(android.telecom.Call.Callback);
     field public static final java.lang.String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+    field public static final java.lang.String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_CONNECTING = 9; // 0x9
     field public static final int STATE_DIALING = 1; // 0x1
@@ -42679,6 +42670,7 @@
     method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
     method public android.text.StaticLayout.Builder setIncludePad(boolean);
     method public android.text.StaticLayout.Builder setIndents(int[], int[]);
+    method public android.text.StaticLayout.Builder setJustify(boolean);
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -46287,6 +46279,7 @@
 
   public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback {
     method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable);
   }
 
   public class SurfaceView extends android.view.View {
@@ -46367,6 +46360,7 @@
     method public void addTouchables(java.util.ArrayList<android.view.View>);
     method public android.view.ViewPropertyAnimator animate();
     method public void announceForAccessibility(java.lang.CharSequence);
+    method public void autoFill(android.view.autofill.AutoFillValue);
     method protected boolean awakenScrollBars();
     method protected boolean awakenScrollBars(int);
     method protected boolean awakenScrollBars(int, boolean);
@@ -46418,8 +46412,8 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public deprecated void dispatchProvideStructure(android.view.ViewStructure);
-    method public void dispatchProvideStructure(android.view.ViewStructure, int);
+    method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
+    method public void dispatchProvideStructure(android.view.ViewStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -46454,6 +46448,8 @@
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
+    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(android.view.autofill.VirtualViewDelegate.Callback);
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -46690,10 +46686,10 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public deprecated void onProvideStructure(android.view.ViewStructure);
-    method public void onProvideStructure(android.view.ViewStructure, int);
-    method public deprecated void onProvideVirtualStructure(android.view.ViewStructure);
-    method public void onProvideVirtualStructure(android.view.ViewStructure, int);
+    method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
+    method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+    method public void onProvideStructure(android.view.ViewStructure);
+    method public void onProvideVirtualStructure(android.view.ViewStructure);
     method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
@@ -46900,8 +46896,8 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
-    field public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 2; // 0x2
-    field public static final int ASSIST_FLAG_SANITIZED_TEXT = 1; // 0x1
+    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 1; // 0x1
+    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 2; // 0x2
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -47531,6 +47527,7 @@
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewStructure asyncNewChild(int);
+    method public abstract android.view.ViewStructure asyncNewChild(int, int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -47539,9 +47536,11 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
+    method public abstract android.view.ViewStructure newChild(int, int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
+    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -48765,6 +48764,80 @@
 
 }
 
+package android.view.autofill {
+
+  public final class AutoFillId implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillId> CREATOR;
+  }
+
+  public final class AutoFillType implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.view.autofill.AutoFillType forList();
+    method public static android.view.autofill.AutoFillType forText(int);
+    method public static android.view.autofill.AutoFillType forToggle();
+    method public int getSubType();
+    method public boolean isList();
+    method public boolean isText();
+    method public boolean isToggle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillType> CREATOR;
+  }
+
+  public final class AutoFillValue implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.view.autofill.AutoFillValue forList(int);
+    method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
+    method public static android.view.autofill.AutoFillValue forToggle(boolean);
+    method public int getListValue();
+    method public java.lang.CharSequence getTextValue();
+    method public boolean getToggleValue();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillValue> CREATOR;
+  }
+
+  public final class Dataset implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.Dataset> CREATOR;
+  }
+
+  public static final class Dataset.Builder {
+    ctor public Dataset.Builder(java.lang.CharSequence);
+    method public android.view.autofill.Dataset build();
+    method public android.view.autofill.Dataset.Builder setExtras(android.os.Bundle);
+    method public android.view.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
+  }
+
+  public final class FillResponse implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.FillResponse> CREATOR;
+  }
+
+  public static final class FillResponse.Builder {
+    ctor public FillResponse.Builder();
+    method public android.view.autofill.FillResponse.Builder addDataset(android.view.autofill.Dataset);
+    method public android.view.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
+    method public android.view.autofill.FillResponse build();
+    method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+  }
+
+  public abstract class VirtualViewDelegate {
+    ctor public VirtualViewDelegate();
+    method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
+  }
+
+  public static abstract class VirtualViewDelegate.Callback {
+    ctor public VirtualViewDelegate.Callback();
+    method public void onFocusChanged(int, boolean);
+    method public void onNodeRemoved(int...);
+    method public void onValueChanged(int);
+  }
+
+}
+
 package android.view.inputmethod {
 
   public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -50280,8 +50353,8 @@
     method public abstract boolean onKeyUp(int, android.view.KeyEvent);
     method public abstract void onMeasure(int, int);
     method public abstract void onOverScrolled(int, int, boolean, boolean);
+    method public default void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
     method public abstract void onProvideVirtualStructure(android.view.ViewStructure);
-    method public default void onProvideVirtualStructure(android.view.ViewStructure, int);
     method public abstract void onScrollChanged(int, int, int, int);
     method public abstract void onSizeChanged(int, int, int, int);
     method public abstract void onStartTemporaryDetach();
@@ -52567,6 +52640,7 @@
     method public boolean getIncludeFontPadding();
     method public android.os.Bundle getInputExtras(boolean);
     method public int getInputType();
+    method public boolean getJustify();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
@@ -52675,6 +52749,7 @@
     method public void setIncludeFontPadding(boolean);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
+    method public void setJustify(boolean);
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7ba88bd..1ba26f5 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -124,6 +124,12 @@
 
 package android.net {
 
+  public class ConnectivityManager {
+    method public deprecated boolean requestRouteToHost(int, int);
+    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
+    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
+  }
+
   public abstract class PskKeyManager {
     ctor public PskKeyManager();
     field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
diff --git a/api/test-current.txt b/api/test-current.txt
index ec530bf..c1ec21d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5423,7 +5423,8 @@
     method public void cancel(int);
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
-    method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
+    method public void createNotificationChannel(android.app.NotificationChannel);
+    method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
     method public void deleteNotificationChannel(java.lang.String);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5458,10 +5459,6 @@
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
-    method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
-  }
-
   public static class NotificationManager.Policy implements android.os.Parcelable {
     ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
@@ -6393,7 +6390,8 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
-    method public int getAutoFillId();
+    method public android.view.autofill.AutoFillId getAutoFillId();
+    method public android.view.autofill.AutoFillType getAutoFillType();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
@@ -6809,6 +6807,7 @@
     method protected android.view.View getErrorView();
     method protected void prepareView(android.view.View);
     method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
+    method public void setAsyncExecutor(java.util.concurrent.Executor);
     method public void updateAppWidget(android.widget.RemoteViews);
     method public void updateAppWidgetOptions(android.os.Bundle);
     method public void updateAppWidgetSize(android.os.Bundle, int, int, int, int);
@@ -24089,11 +24088,8 @@
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
-    method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
     method public static deprecated boolean setProcessDefaultNetwork(android.net.Network);
-    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
-    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
     method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     method public void unregisterNetworkCallback(android.app.PendingIntent);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
@@ -28670,7 +28666,7 @@
     method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
     method public void surfaceCreated(android.view.SurfaceHolder);
     method public void surfaceDestroyed(android.view.SurfaceHolder);
-    method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public deprecated void surfaceRedrawNeeded(android.view.SurfaceHolder);
     field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
     field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
     field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -31049,6 +31045,7 @@
     field public static final java.lang.String ACTION_SET_ALARM = "android.intent.action.SET_ALARM";
     field public static final java.lang.String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
     field public static final java.lang.String ACTION_SHOW_ALARMS = "android.intent.action.SHOW_ALARMS";
+    field public static final java.lang.String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
     field public static final java.lang.String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
     field public static final java.lang.String ALARM_SEARCH_MODE_ALL = "android.all";
     field public static final java.lang.String ALARM_SEARCH_MODE_LABEL = "android.label";
@@ -35162,26 +35159,19 @@
     method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
     method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
+    field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
+    field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
   }
 
   public final class FillCallback {
     method public void onFailure(java.lang.CharSequence);
-    method public void onSuccess(android.service.autofill.FillCallback.FillData);
-  }
-
-  public static final class FillCallback.FillData {
-  }
-
-  public static class FillCallback.FillData.Builder {
-    ctor public FillCallback.FillData.Builder();
-    method public android.service.autofill.FillCallback.FillData build();
-    method public android.service.autofill.FillCallback.FillData.Builder setTextField(int, java.lang.String);
+    method public void onSuccess(android.view.autofill.FillResponse);
   }
 
   public final class SaveCallback {
     method public void onFailure(java.lang.CharSequence);
-    method public void onSuccess(int[]);
+    method public void onSuccess(android.view.autofill.AutoFillId[]);
   }
 
 }
@@ -36846,6 +36836,7 @@
     method public void unhold();
     method public void unregisterCallback(android.telecom.Call.Callback);
     field public static final java.lang.String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
+    field public static final java.lang.String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_CONNECTING = 9; // 0x9
     field public static final int STATE_DIALING = 1; // 0x1
@@ -39581,6 +39572,7 @@
     method public android.text.StaticLayout.Builder setHyphenationFrequency(int);
     method public android.text.StaticLayout.Builder setIncludePad(boolean);
     method public android.text.StaticLayout.Builder setIndents(int[], int[]);
+    method public android.text.StaticLayout.Builder setJustify(boolean);
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
@@ -43358,6 +43350,7 @@
 
   public static abstract interface SurfaceHolder.Callback2 implements android.view.SurfaceHolder.Callback {
     method public abstract void surfaceRedrawNeeded(android.view.SurfaceHolder);
+    method public default void surfaceRedrawNeededAsync(android.view.SurfaceHolder, java.lang.Runnable);
   }
 
   public class SurfaceView extends android.view.View {
@@ -43438,6 +43431,7 @@
     method public void addTouchables(java.util.ArrayList<android.view.View>);
     method public android.view.ViewPropertyAnimator animate();
     method public void announceForAccessibility(java.lang.CharSequence);
+    method public void autoFill(android.view.autofill.AutoFillValue);
     method protected boolean awakenScrollBars();
     method protected boolean awakenScrollBars(int);
     method protected boolean awakenScrollBars(int, boolean);
@@ -43489,8 +43483,8 @@
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public deprecated void dispatchProvideStructure(android.view.ViewStructure);
-    method public void dispatchProvideStructure(android.view.ViewStructure, int);
+    method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
+    method public void dispatchProvideStructure(android.view.ViewStructure);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSetActivated(boolean);
@@ -43525,6 +43519,8 @@
     method public float getAlpha();
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
+    method public android.view.autofill.AutoFillType getAutoFillType();
+    method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate(android.view.autofill.VirtualViewDelegate.Callback);
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -43762,10 +43758,10 @@
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
-    method public deprecated void onProvideStructure(android.view.ViewStructure);
-    method public void onProvideStructure(android.view.ViewStructure, int);
-    method public deprecated void onProvideVirtualStructure(android.view.ViewStructure);
-    method public void onProvideVirtualStructure(android.view.ViewStructure, int);
+    method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
+    method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
+    method public void onProvideStructure(android.view.ViewStructure);
+    method public void onProvideVirtualStructure(android.view.ViewStructure);
     method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method public void onRtlPropertiesChanged(int);
@@ -43972,8 +43968,8 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
-    field public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 2; // 0x2
-    field public static final int ASSIST_FLAG_SANITIZED_TEXT = 1; // 0x1
+    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 1; // 0x1
+    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 2; // 0x2
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -44607,6 +44603,7 @@
     method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewStructure asyncNewChild(int);
+    method public abstract android.view.ViewStructure asyncNewChild(int, int);
     method public abstract int getChildCount();
     method public abstract android.os.Bundle getExtras();
     method public abstract java.lang.CharSequence getHint();
@@ -44615,9 +44612,11 @@
     method public abstract int getTextSelectionStart();
     method public abstract boolean hasExtras();
     method public abstract android.view.ViewStructure newChild(int);
+    method public abstract android.view.ViewStructure newChild(int, int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
     method public abstract void setAlpha(float);
+    method public abstract void setAutoFillType(android.view.autofill.AutoFillType);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -45840,6 +45839,80 @@
 
 }
 
+package android.view.autofill {
+
+  public final class AutoFillId implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillId> CREATOR;
+  }
+
+  public final class AutoFillType implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.view.autofill.AutoFillType forList();
+    method public static android.view.autofill.AutoFillType forText(int);
+    method public static android.view.autofill.AutoFillType forToggle();
+    method public int getSubType();
+    method public boolean isList();
+    method public boolean isText();
+    method public boolean isToggle();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillType> CREATOR;
+  }
+
+  public final class AutoFillValue implements android.os.Parcelable {
+    method public int describeContents();
+    method public static android.view.autofill.AutoFillValue forList(int);
+    method public static android.view.autofill.AutoFillValue forText(java.lang.CharSequence);
+    method public static android.view.autofill.AutoFillValue forToggle(boolean);
+    method public int getListValue();
+    method public java.lang.CharSequence getTextValue();
+    method public boolean getToggleValue();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.AutoFillValue> CREATOR;
+  }
+
+  public final class Dataset implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.Dataset> CREATOR;
+  }
+
+  public static final class Dataset.Builder {
+    ctor public Dataset.Builder(java.lang.CharSequence);
+    method public android.view.autofill.Dataset build();
+    method public android.view.autofill.Dataset.Builder setExtras(android.os.Bundle);
+    method public android.view.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
+  }
+
+  public final class FillResponse implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.autofill.FillResponse> CREATOR;
+  }
+
+  public static final class FillResponse.Builder {
+    ctor public FillResponse.Builder();
+    method public android.view.autofill.FillResponse.Builder addDataset(android.view.autofill.Dataset);
+    method public android.view.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
+    method public android.view.autofill.FillResponse build();
+    method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+  }
+
+  public abstract class VirtualViewDelegate {
+    ctor public VirtualViewDelegate();
+    method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
+  }
+
+  public static abstract class VirtualViewDelegate.Callback {
+    ctor public VirtualViewDelegate.Callback();
+    method public void onFocusChanged(int, boolean);
+    method public void onNodeRemoved(int...);
+    method public void onValueChanged(int);
+  }
+
+}
+
 package android.view.inputmethod {
 
   public class BaseInputConnection implements android.view.inputmethod.InputConnection {
@@ -49291,6 +49364,7 @@
     method public boolean getIncludeFontPadding();
     method public android.os.Bundle getInputExtras(boolean);
     method public int getInputType();
+    method public boolean getJustify();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
     method public float getLetterSpacing();
@@ -49399,6 +49473,7 @@
     method public void setIncludeFontPadding(boolean);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
+    method public void setJustify(boolean);
     method public void setKeyListener(android.text.method.KeyListener);
     method public void setLetterSpacing(float);
     method public void setLineSpacing(float, float);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d7a8bce..ab22b6e 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -126,6 +126,12 @@
 
 package android.net {
 
+  public class ConnectivityManager {
+    method public deprecated boolean requestRouteToHost(int, int);
+    method public deprecated int startUsingNetworkFeature(int, java.lang.String);
+    method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
+  }
+
   public abstract class PskKeyManager {
     ctor public PskKeyManager();
     field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2ccfe0e..87e5416 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -70,9 +70,8 @@
 import android.os.StrictMode;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.service.autofill.FillableInputField;
 import android.service.autofill.AutoFillService;
-import android.service.autofill.IAutoFillCallback;
+import android.service.autofill.IAutoFillAppCallback;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.TextAssistant;
@@ -115,6 +114,11 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.autofill.VirtualViewDelegate;
+import android.view.autofill.Dataset;
+import android.view.autofill.DatasetField;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.FillResponse;
 import android.widget.AdapterView;
 import android.widget.EditText;
 import android.widget.Toast;
@@ -130,6 +134,7 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -697,6 +702,9 @@
     private static final String TAG = "Activity";
     private static final boolean DEBUG_LIFECYCLE = false;
 
+    // TODO(b/33197203): set to false once stable
+    private static final boolean DEBUG_AUTO_FILL = true;
+
     /** Standard activity result: operation canceled. */
     public static final int RESULT_CANCELED    = 0;
     /** Standard activity result: operation succeeded. */
@@ -847,7 +855,10 @@
     private boolean mEatKeyUpEvent;
 
     @GuardedBy("this")
-    private IAutoFillCallback mAutoFillCallback;
+    private WeakReference<IAutoFillAppCallback> mAutoFillCallback;
+
+    @GuardedBy("this")
+    private VirtualViewDelegate.Callback mAutoFillDelegateCallback;
 
     private static native String getDlWarning();
 
@@ -1718,47 +1729,73 @@
     }
 
     /**
-     * Lazily gets the {@code IAutoFillCallback} for this activitity.
+     * Lazily sets the {@link #mAutoFillDelegateCallback}.
+     */
+    private void setAutoFillDelegateCallback() {
+        synchronized (this) {
+            if (mAutoFillDelegateCallback == null) {
+                mAutoFillDelegateCallback = new VirtualViewDelegate.Callback() {
+                    // TODO(b/33197203): implement
+                };
+            }
+        }
+    }
+
+    /**
+     * Lazily gets the {@link IAutoFillAppCallback} for this activitity.
      *
      * <p>This callback is used by the {@link AutoFillService} app to auto-fill the activity fields.
      */
-    IAutoFillCallback getAutoFillCallback() {
+    WeakReference<IAutoFillAppCallback> getAutoFillCallback() {
         synchronized (this) {
             if (mAutoFillCallback == null) {
-                mAutoFillCallback = new IAutoFillCallback.Stub() {
+                final IAutoFillAppCallback cb = new IAutoFillAppCallback.Stub() {
                     @Override
-                    public void autofill(@SuppressWarnings("rawtypes") List fields)
-                            throws RemoteException {
+                    public void autoFill(Dataset dataset) throws RemoteException {
+                        // TODO(b/33197203): must keep the dataset so subsequent calls pass the same
+                        // dataset.extras to service
                         runOnUiThread(() -> {
                             final View root = getWindow().getDecorView().getRootView();
-                            for (Object field : fields) {
-                                if (!(field instanceof FillableInputField)) {
-                                    Slog.w(TAG,  "autofill(): invalid type " + field.getClass());
+                            for (DatasetField field : dataset.getFields()) {
+                                final AutoFillId id = field.getId();
+                                if (id == null) {
+                                    Log.w(TAG, "autoFill(): null id on " + field);
                                     continue;
                                 }
-                                FillableInputField autoFillField = (FillableInputField) field;
-                                final int viewId = autoFillField.getId();
+                                final int viewId = id.getViewId();
                                 final View view = root.findViewByAccessibilityIdTraversal(viewId);
-                                // TODO(b/33197203): should handle other types of view as well, but
-                                // that will require:
-                                // - a new interface like AutoFillable
-                                // - a way for the views to define the type of the autofield value
-                                if ((view instanceof EditText)) {
-                                    ((EditText) view).setText(autoFillField.getValue());
+                                if (view == null) {
+                                    Log.w(TAG, "autoFill(): no View with id " + viewId);
+                                    continue;
+                                }
+
+                                // TODO(b/33197203): handle protected value (like credit card)
+                                if (id.isVirtual()) {
+                                    // Delegate virtual fields to provider.
+                                    setAutoFillDelegateCallback();
+                                    final VirtualViewDelegate mgr = view
+                                            .getAutoFillVirtualViewDelegate(
+                                                    mAutoFillDelegateCallback);
+                                    if (mgr == null) {
+                                        Log.w(TAG, "autoFill(): cannot fill virtual " + id
+                                                + "; no auto-fill provider for view "
+                                                + view.getClass());
+                                        continue;
+                                    }
+                                    if (DEBUG_AUTO_FILL) {
+                                        Log.d(TAG, "autoFill(): delegating " + id
+                                                + " to virtual manager  " + mgr);
+                                    }
+                                    mgr.autoFill(id.getVirtualChildId(), field.getValue());
+                                } else {
+                                    // Handle non-virtual fields itself.
+                                    view.autoFill(field.getValue());
                                 }
                             }
                         });
                     }
-
-                    @Override
-                    public void showError(String message) {
-                        runOnUiThread(() -> {
-                            // TODO(b/33197203): temporary show a toast until it uses the Snack bar.
-                            Toast.makeText(Activity.this, "Auto-fill request failed: " + message,
-                                    Toast.LENGTH_LONG).show();
-                        });
-                    }
                 };
+                mAutoFillCallback = new WeakReference<IAutoFillAppCallback>(cb);
             }
         }
         return mAutoFillCallback;
@@ -4341,8 +4378,8 @@
      * that are defined to return a result.  In other protocols (such as
      * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
      * not get the result when you expect.  For example, if the activity you
-     * are launching uses the singleTask launch mode, it will not run in your
-     * task and thus you will immediately receive a cancel result.
+     * are launching uses {@link Intent#FLAG_ACTIVITY_NEW_TASK}, it will not
+     * run in your task and thus you will immediately receive a cancel result.
      *
      * <p>As a special case, if you call startActivityForResult() with a requestCode
      * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
@@ -6096,7 +6133,7 @@
 
         if (mAutoFillCallback != null) {
             writer.print(prefix); writer.print("mAutoFillCallback: " );
-                    writer.println(mAutoFillCallback);
+                    writer.println(mAutoFillCallback.get());
         }
 
         mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index cd50c4d..d362b01 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -483,6 +483,12 @@
     /** @hide requestType for assist context: generate full AssistStructure. */
     public static final int ASSIST_CONTEXT_FULL = 1;
 
+    /** @hide requestType for assist context: generate full AssistStructure for auto-fill. */
+    public static final int ASSIST_CONTEXT_AUTO_FILL = 2;
+
+    /** @hide requestType for assist context: generate full AssistStructure for auto-fill save. */
+    public static final int ASSIST_CONTEXT_AUTO_FILL_SAVE = 3;
+
     /** @hide Flag for registerUidObserver: report changes in process state. */
     public static final int UID_OBSERVER_PROCSTATE = 1<<0;
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e34fabc..e3bbc92 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -89,7 +89,7 @@
 import android.security.NetworkSecurityPolicy;
 import android.security.net.config.NetworkSecurityConfigProvider;
 import android.service.autofill.AutoFillService;
-import android.service.autofill.IAutoFillCallback;
+import android.service.autofill.IAutoFillAppCallback;
 import android.service.voice.VoiceInteractionSession;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
@@ -2884,9 +2884,8 @@
         // - it does not call onProvideAssistData()
         // - it needs an IAutoFillCallback
         // - it sets the flags so views can provide autofill-specific data (such as passwords)
-        boolean forAutoFill = (cmd.flags
-                & (View.ASSIST_FLAG_SANITIZED_TEXT
-                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+        boolean forAutoFill = cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTO_FILL
+                || cmd.requestType == ActivityManager.ASSIST_CONTEXT_AUTO_FILL_SAVE;
 
         // TODO(b/33197203): decide if lastSessionId logic applies to auto-fill sessions
         if (mLastSessionId != cmd.sessionId) {
@@ -2910,22 +2909,23 @@
             if (!forAutoFill) {
                 r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
                 r.activity.onProvideAssistData(data);
+                referrer = r.activity.onProvideReferrer();
             }
-            referrer = r.activity.onProvideReferrer();
             if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutoFill) {
                 structure = new AssistStructure(r.activity, cmd.flags);
                 Intent activityIntent = r.activity.getIntent();
-                if (cmd.flags > 0) {
+                if (forAutoFill) {
                     data.putInt(VoiceInteractionSession.KEY_FLAGS, cmd.flags);
                 }
+                boolean addAutoFillCallback = false;
                 // TODO(b/33197203): re-evaluate conditions below for auto-fill. In particular,
                 // FLAG_SECURE might be allowed on AUTO_FILL but not on AUTO_FILL_SAVE)
-                if (activityIntent != null && (r.window == null ||
+                boolean notSecure = r.window == null ||
                         (r.window.getAttributes().flags
-                                & WindowManager.LayoutParams.FLAG_SECURE) == 0)) {
+                                & WindowManager.LayoutParams.FLAG_SECURE) == 0;
+                if (activityIntent != null && notSecure) {
                     if (forAutoFill) {
-                        IAutoFillCallback autoFillCallback = r.activity.getAutoFillCallback();
-                        data.putBinder(AutoFillService.KEY_CALLBACK, autoFillCallback.asBinder());
+                        addAutoFillCallback = true;
                     } else {
                         Intent intent = new Intent(activityIntent);
                         intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
@@ -2936,10 +2936,21 @@
                 } else {
                     if (!forAutoFill) {
                         content.setDefaultIntent(new Intent());
+                    } else {
+                        // activityIntent is unlikely to be null, but if it is, we should still
+                        // set the auto-fill callback.
+                        addAutoFillCallback = notSecure;
                     }
                 }
                 if (!forAutoFill) {
                     r.activity.onProvideAssistContent(content);
+                } else if (addAutoFillCallback) {
+                    IAutoFillAppCallback cb = r.activity.getAutoFillCallback().get();
+                    if (cb != null) {
+                        data.putBinder(AutoFillService.KEY_CALLBACK, cb.asBinder());
+                    } else {
+                        Slog.w(TAG, "handleRequestAssistContextExtras(): callback was GCed");
+                    }
                 }
             }
         }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 21854d3..a2d9c45 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -586,7 +586,7 @@
     void unregisterTaskStackListener(ITaskStackListener listener);
     void moveStackToDisplay(int stackId, int displayId);
     boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
-            in IBinder activityToken, int flags);
+            int resultCode, in IBinder activityToken, int flags);
     void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
     int restartUserInBackground(int userId);
 
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 4d5f67b..81aeaef 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -17,7 +17,6 @@
 
 package android.app;
 
-import android.app.IOnNotificationChannelCreatedListener;
 import android.app.ITransientNotification;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -52,8 +51,7 @@
     boolean areNotificationsEnabled(String pkg);
     int getPackageImportance(String pkg);
 
-    void createNotificationChannel(String pkg, in NotificationChannel channel,
-            in IOnNotificationChannelCreatedListener listener);
+    void createNotificationChannels(String pkg, in ParceledListSlice channelsList);
     void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
     NotificationChannel getNotificationChannel(String pkg, String channelId);
     NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId);
diff --git a/core/java/android/app/IOnNotificationChannelCreatedListener.aidl b/core/java/android/app/IOnNotificationChannelCreatedListener.aidl
deleted file mode 100644
index 8e66542..0000000
--- a/core/java/android/app/IOnNotificationChannelCreatedListener.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-**
-** Copyright 2016, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.app;
-
-import android.app.NotificationChannel;
-
-/** {@hide} */
-oneway interface IOnNotificationChannelCreatedListener {
-    void onNotificationChannelCreated(in NotificationChannel channel);
-}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index a9ff482..3551691 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -47,6 +47,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -381,42 +382,26 @@
     }
 
     /**
-     * Listener passed to {@link NotificationManager#createNotificationChannel} to notify
-     * caller of result.
+     * Creates a notification channel that notifications can be posted to.
+     *
+     * @param channel  the channel to create.  Note that the created channel may differ from this
+     *                 value.  If the channel already exists, it will not be modified.
      */
-    public interface OnNotificationChannelCreatedListener {
-        /**
-         * @param createdChannel NotificationChannel created by the system.  Value is null iff an
-         *   exception was thrown during channel creation.
-         */
-        public void onNotificationChannelCreated(NotificationChannel createdChannel);
+    public void createNotificationChannel(@NonNull NotificationChannel channel) {
+        createNotificationChannels(Arrays.asList(channel));
     }
 
     /**
-     * Creates a notification channel that notifications can be posted to.
+     * Creates multiple notification channels that different notifications can be posted to.
      *
-     * @param channel  the channel to attempt to create.  Note that the created channel may differ
-     *                 from this value.
-     * @param listener Called when operation is finished.
-     * @param handler  The handler to invoke the listener on, or {@code null} to use the main
-     *                 handler.
+     * @param channels the list of channels to attempt to create.  If any of these channels already
+     *                 exist, they will not be modified.
      */
-    public void createNotificationChannel(
-            @NonNull NotificationChannel channel,
-            @NonNull OnNotificationChannelCreatedListener listener,
-            @Nullable Handler handler) {
+    public void createNotificationChannels(@NonNull List<NotificationChannel> channels) {
         INotificationManager service = getService();
         try {
-            final Handler actualHandler =
-                    handler != null ? handler : new Handler(Looper.getMainLooper());
-            service.createNotificationChannel(mContext.getPackageName(), channel,
-                    new IOnNotificationChannelCreatedListener.Stub() {
-                        @Override public void onNotificationChannelCreated(
-                                NotificationChannel channel) {
-                            actualHandler.post(
-                                    () -> { listener.onNotificationChannelCreated(channel); });
-                        }
-                    });
+            service.createNotificationChannels(mContext.getPackageName(),
+                    new ParceledListSlice(channels));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 1988e42..b94264e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -21,6 +21,8 @@
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillId;
 
 import java.util.ArrayList;
 
@@ -411,25 +413,30 @@
             mTitle = root.getTitle();
             mDisplayId = root.getDisplayId();
             mRoot = new ViewNode();
+
+            // Must explicitly call the proper method based on flags since we don't know which
+            // method (if any) was overridden by the View subclass.
+            boolean forAutoFill = (flags
+                    & (View.AUTO_FILL_FLAG_TYPE_FILL
+                            | View.AUTO_FILL_FLAG_TYPE_SAVE)) != 0;
+
             ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
             if ((root.getWindowFlags()& WindowManager.LayoutParams.FLAG_SECURE) != 0) {
                 // This is a secure window, so it doesn't want a screenshot, and that
                 // means we should also not copy out its view hierarchy.
 
-                // Must explicitly set which method to calls since View subclasses might
-                // have implemented the deprecated method.
-                if (flags == 0) {
-                    view.onProvideStructure(builder);
+                if (forAutoFill) {
+                    view.onProvideAutoFillStructure(builder, flags);
                 } else {
-                    view.onProvideStructure(builder, flags);
+                    view.onProvideStructure(builder);
                 }
                 builder.setAssistBlocked(true);
                 return;
             }
-            if (flags == 0) {
-                view.dispatchProvideStructure(builder);
+            if (forAutoFill) {
+                view.dispatchProvideAutoFillStructure(builder, flags);
             } else {
-                view.dispatchProvideStructure(builder, flags);
+                view.dispatchProvideStructure(builder);
             }
         }
 
@@ -526,7 +533,10 @@
         String mIdPackage;
         String mIdType;
         String mIdEntry;
-        int mAutoFillId = View.NO_ID;
+        // TODO(b/33197203): once we have more flags, it might be better to store the individual
+        // fields (viewId and childId) of the field.
+        AutoFillId mAutoFillId;
+        AutoFillType mAutoFillType;
         int mX;
         int mY;
         int mScrollX;
@@ -551,7 +561,11 @@
         static final int FLAGS_ACTIVATED = 0x00002000;
         static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
 
-        static final int FLAGS_HAS_AUTO_FILL_ID = 0x80000000;
+        // TODO(b/33197203): auto-fill data is made of many fields and ideally we should verify
+        // one-by-one to optimize what's sent over, but there isn't enough flag bits for that, we'd
+        // need to create a 'flags2' or 'autoFillFlags' field and add these flags there.
+        // So, to keep thinkg simpler for now, let's just use on flag for all of them...
+        static final int FLAGS_HAS_AUTO_FILL_DATA = 0x80000000;
         static final int FLAGS_HAS_MATRIX = 0x40000000;
         static final int FLAGS_HAS_ALPHA = 0x20000000;
         static final int FLAGS_HAS_ELEVATION = 0x10000000;
@@ -595,8 +609,9 @@
                     }
                 }
             }
-            if ((flags&FLAGS_HAS_AUTO_FILL_ID) != 0) {
-                mAutoFillId = in.readInt();
+            if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
+                mAutoFillId = in.readParcelable(null);
+                mAutoFillType = in.readParcelable(null);
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 mX = in.readInt();
@@ -653,8 +668,8 @@
             if (mId != View.NO_ID) {
                 flags |= FLAGS_HAS_ID;
             }
-            if (mAutoFillId != View.NO_ID) {
-                flags |= FLAGS_HAS_AUTO_FILL_ID;
+            if (mAutoFillId != null) {
+                flags |= FLAGS_HAS_AUTO_FILL_DATA;
             }
             if ((mX&~0x7fff) != 0 || (mY&~0x7fff) != 0
                     || (mWidth&~0x7fff) != 0 | (mHeight&~0x7fff) != 0) {
@@ -700,8 +715,9 @@
                     }
                 }
             }
-            if ((flags&FLAGS_HAS_AUTO_FILL_ID) != 0) {
-                out.writeInt(mAutoFillId);
+            if ((flags&FLAGS_HAS_AUTO_FILL_DATA) != 0) {
+                out.writeParcelable(mAutoFillId, 0);
+                out.writeParcelable(mAutoFillType,  0);
             }
             if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
                 out.writeInt(mX);
@@ -773,16 +789,26 @@
         }
 
         /**
-         * Returns the id that can be used to auto-fill the view.
+         * Gets the id that can be used to auto-fill the view contents.
          *
          * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
          * for assist.
          */
-        public int getAutoFillId() {
+        public AutoFillId getAutoFillId() {
             return mAutoFillId;
         }
 
         /**
+         * Gets the the type of value that can be used to auto-fill the view contents.
+         *
+         * <p>It's only set when the {@link AssistStructure} is used for auto-filling purposes, not
+         * for assist.
+         */
+        public AutoFillType getAutoFillType() {
+            return mAutoFillType;
+        }
+
+        /**
          * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
          */
         public int getLeft() {
@@ -1318,17 +1344,23 @@
             return mNode.mChildren != null ? mNode.mChildren.length : 0;
         }
 
-        @Override
-        public ViewStructure newChild(int index) {
+        private void setAutoFillId(ViewNode child, boolean forAutoFill, int virtualId) {
+            if (forAutoFill) {
+                child.mAutoFillId = new AutoFillId(mNode.mAutoFillId, virtualId);
+            }
+        }
+
+        private ViewStructure newChild(int index, boolean forAutoFill, int virtualId) {
             ViewNode node = new ViewNode();
+            setAutoFillId(node, forAutoFill, virtualId);
             mNode.mChildren[index] = node;
             return new ViewNodeBuilder(mAssist, node, false);
         }
 
-        @Override
-        public ViewStructure asyncNewChild(int index) {
+        private ViewStructure asyncNewChild(int index, boolean forAutoFill, int virtualId) {
             synchronized (mAssist) {
                 ViewNode node = new ViewNode();
+                setAutoFillId(node, forAutoFill, virtualId);
                 mNode.mChildren[index] = node;
                 ViewNodeBuilder builder = new ViewNodeBuilder(mAssist, node, true);
                 mAssist.mPendingAsyncChildren.add(builder);
@@ -1337,6 +1369,26 @@
         }
 
         @Override
+        public ViewStructure newChild(int index) {
+            return newChild(index, false, 0);
+        }
+
+        @Override
+        public ViewStructure newChild(int index, int virtualId) {
+            return newChild(index, true, virtualId);
+        }
+
+        @Override
+        public ViewStructure asyncNewChild(int index) {
+            return asyncNewChild(index, false, 0);
+        }
+
+        @Override
+        public ViewStructure asyncNewChild(int index, int virtualId) {
+            return asyncNewChild(index, true, virtualId);
+        }
+
+        @Override
         public void asyncCommit() {
             synchronized (mAssist) {
                 if (!mAsync) {
@@ -1356,9 +1408,20 @@
         }
 
         @Override
-        public void setAutoFillId(int autoFillId) {
-            mNode.mAutoFillId = autoFillId;
+        public void setAutoFillId(int viewId) {
+            mNode.mAutoFillId = new AutoFillId(viewId);
         }
+
+        @Override
+        public AutoFillId getAutoFillId() {
+            return mNode.mAutoFillId;
+        }
+
+        @Override
+        public void setAutoFillType(AutoFillType type) {
+           mNode.mAutoFillType = type;
+        }
+
     }
 
     /** @hide */
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 4c8360f..ef3b1c5 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -347,11 +347,11 @@
     }
 
     /**
-     * Sets an executor which can be used for asynchronously inflating and applying the remoteviews.
-     * @see {@link RemoteViews#applyAsync(Context, ViewGroup, RemoteViews.OnViewAppliedListener, Executor)}
+     * Sets an executor which can be used for asynchronously inflating. CPU intensive tasks like
+     * view inflation or loading images will be performed on the executor. The updates will still
+     * be applied on the UI thread.
      *
      * @param executor the executor to use or null.
-     * @hide
      */
     public void setAsyncExecutor(Executor executor) {
         if (mLastExecutionSignal != null) {
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index b686938..98a5341 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -243,7 +243,7 @@
         }
 
         as.mPfd = new ParcelFileDescriptor(fds[0]);
-        as.mSocket = new LocalSocket(fds[0]);
+        as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
         as.mSocketIS = as.mSocket.getInputStream();
         as.mSocketOS = as.mSocket.getOutputStream();
         as.mAddress = RemoteAddr;
@@ -367,7 +367,7 @@
                 if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
                 if (mPfd == null) throw new IOException("bt socket connect failed");
                 FileDescriptor fd = mPfd.getFileDescriptor();
-                mSocket = new LocalSocket(fd);
+                mSocket = LocalSocket.createConnectedLocalSocket(fd);
                 mSocketIS = mSocket.getInputStream();
                 mSocketOS = mSocket.getOutputStream();
             }
@@ -416,9 +416,9 @@
                 if(mSocketState != SocketState.INIT) return EBADFD;
                 if(mPfd == null) return -1;
                 FileDescriptor fd = mPfd.getFileDescriptor();
-                if (DBG) Log.d(TAG, "bindListen(), new LocalSocket ");
-                mSocket = new LocalSocket(fd);
-                if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream() ");
+                if (DBG) Log.d(TAG, "bindListen(), Create LocalSocket");
+                mSocket = LocalSocket.createConnectedLocalSocket(fd);
+                if (DBG) Log.d(TAG, "bindListen(), new LocalSocket.getInputStream()");
                 mSocketIS = mSocket.getInputStream();
                 mSocketOS = mSocket.getOutputStream();
             }
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 13ba6cc..aea1258 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -167,6 +167,8 @@
         public static final int POLICY_DIM = 2;
         // Policy: Make the screen bright as usual.
         public static final int POLICY_BRIGHT = 3;
+        // Policy: Keep the screen and display optimized for VR mode.
+        public static final int POLICY_VR = 4;
 
         // The basic overall policy to apply: off, doze, dim or bright.
         public int policy;
@@ -233,6 +235,10 @@
             return policy == POLICY_BRIGHT || policy == POLICY_DIM;
         }
 
+        public boolean isVr() {
+            return policy == POLICY_VR;
+        }
+
         public void copyFrom(DisplayPowerRequest other) {
             policy = other.policy;
             useProximitySensor = other.useProximitySensor;
@@ -301,6 +307,8 @@
                     return "DIM";
                 case POLICY_BRIGHT:
                     return "BRIGHT";
+                case POLICY_VR:
+                    return "VR";
                 default:
                     return Integer.toString(policy);
             }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d1d5f40..ac0c0dc 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1163,6 +1163,7 @@
      *             {@link #requestNetwork(NetworkRequest, NetworkCallback)} API.
      *             In {@link VERSION_CODES#M}, and above, this method is unsupported and will
      *             throw {@code UnsupportedOperationException} if called.
+     * @removed
      */
     @Deprecated
     public int startUsingNetworkFeature(int networkType, String feature) {
@@ -1219,6 +1220,7 @@
      *             {@link #unregisterNetworkCallback(NetworkCallback)} API.
      *             In {@link VERSION_CODES#M}, and above, this method is unsupported and will
      *             throw {@code UnsupportedOperationException} if called.
+     * @removed
      */
     @Deprecated
     public int stopUsingNetworkFeature(int networkType, String feature) {
@@ -1633,6 +1635,7 @@
      *             {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} API.
      *             In {@link VERSION_CODES#M}, and above, this method is unsupported and will
      *             throw {@code UnsupportedOperationException} if called.
+     * @removed
      */
     @Deprecated
     public boolean requestRouteToHost(int networkType, int hostAddress) {
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 932f031..9573953 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -100,4 +100,21 @@
      * @hide
      */
     boolean requestScores(in NetworkKey[] networks);
+
+    /**
+     * Determine whether the application with the given UID is the enabled scorer.
+     *
+     * @param callingUid the UID to check
+     * @return true if the provided UID is the active scorer, false otherwise.
+     * @hide
+     */
+    boolean isCallerActiveScorer(int callingUid);
+
+    /**
+     * Obtain the package name of the current active network scorer.
+     *
+     * @return the full package name of the current active scorer, or null if there is no active
+     *         scorer.
+     */
+    String getActiveScorerPackage();
 }
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index e1eaf00..3fcde330 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -89,7 +89,7 @@
 
         impl.accept(acceptedImpl);
 
-        return LocalSocket.createLocalSocketForAccept(acceptedImpl, LocalSocket.SOCKET_UNKNOWN);
+        return LocalSocket.createLocalSocketForAccept(acceptedImpl);
     }
 
     /**
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index d9ad74b..8afa1ed 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -31,6 +31,7 @@
 public class LocalSocket implements Closeable {
 
     private final LocalSocketImpl impl;
+    /** false if impl.create() needs to be called */
     private volatile boolean implCreated;
     private LocalSocketAddress localAddress;
     private boolean isBound;
@@ -61,19 +62,6 @@
      */
     public LocalSocket(int sockType) {
         this(new LocalSocketImpl(), sockType);
-        isBound = false;
-        isConnected = false;
-    }
-
-    /**
-     * Creates a AF_LOCAL/UNIX domain stream socket with FileDescriptor.
-     * @hide
-     */
-    public LocalSocket(FileDescriptor fd) throws IOException {
-        this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
-        isBound = true;
-        isConnected = true;
-        implCreated = true;
     }
 
     private LocalSocket(LocalSocketImpl impl, int sockType) {
@@ -84,9 +72,27 @@
     }
 
     /**
+     * Creates a LocalSocket instances using the FileDescriptor for an already-connected
+     * AF_LOCAL/UNIX domain stream socket. Note: the FileDescriptor must be closed by the caller:
+     * closing the LocalSocket will not close it.
+     *
+     * @hide - used by BluetoothSocket.
+     */
+    public static LocalSocket createConnectedLocalSocket(FileDescriptor fd) {
+        return createConnectedLocalSocket(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
+    }
+
+    /**
      * for use with LocalServerSocket.accept()
      */
-    static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl, int sockType) {
+    static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl) {
+        return createConnectedLocalSocket(impl, SOCKET_UNKNOWN);
+    }
+
+    /**
+     * Creates a LocalSocket from an existing LocalSocketImpl that is already connected.
+     */
+    private static LocalSocket createConnectedLocalSocket(LocalSocketImpl impl, int sockType) {
         LocalSocket socket = new LocalSocket(impl, sockType);
         socket.isConnected = true;
         socket.isBound = true;
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index d8f7821..05c8afb 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -218,7 +218,7 @@
      *
      * @param fd non-null; bound file descriptor
      */
-    /*package*/ LocalSocketImpl(FileDescriptor fd) throws IOException
+    /*package*/ LocalSocketImpl(FileDescriptor fd)
     {
         this.fd = fd;
     }
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 717ac70..2870dd6 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -168,11 +168,11 @@
      *         scorer.
      */
     public String getActiveScorerPackage() {
-        NetworkScorerAppData app = new NetworkScorerAppManager(mContext).getActiveScorer();
-        if (app == null) {
-            return null;
+        try {
+            return mService.getActiveScorerPackage();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-        return app.packageName;
     }
 
     /**
@@ -339,4 +339,19 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Determine whether the application with the given UID is the enabled scorer.
+     *
+     * @param callingUid the UID to check
+     * @return true if the provided UID is the active scorer, false otherwise.
+     * @hide
+     */
+    public boolean isCallerActiveScorer(int callingUid) {
+        try {
+            return mService.isCallerActiveScorer(callingUid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index ec0bb25d..23d5af5 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -16,7 +16,6 @@
 
 package android.net;
 
-import android.Manifest;
 import android.Manifest.permission;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
@@ -28,7 +27,9 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+
 import com.android.internal.R;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -226,6 +227,7 @@
     }
 
     /** Determine whether the application with the given UID is the enabled scorer. */
+    @Deprecated // Use NetworkScoreManager.isCallerActiveScorer()
     public boolean isCallerActiveScorer(int callingUid) {
         NetworkScorerAppData defaultApp = getActiveScorer();
         if (defaultApp == null) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 9d04929..dff0a28 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -49,23 +49,23 @@
  * <i>These levels are mutually exclusive - you may only specify one of them.</i>
  *
  * <table>
- *     <tr><th>Flag Value</th> 
+ *     <tr><th>Flag Value</th>
  *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
  *
  *     <tr><td>{@link #PARTIAL_WAKE_LOCK}</td>
- *         <td>On*</td> <td>Off</td> <td>Off</td> 
+ *         <td>On*</td> <td>Off</td> <td>Off</td>
  *     </tr>
- *     
+ *
  *     <tr><td>{@link #SCREEN_DIM_WAKE_LOCK}</td>
- *         <td>On</td> <td>Dim</td> <td>Off</td> 
+ *         <td>On</td> <td>Dim</td> <td>Off</td>
  *     </tr>
  *
  *     <tr><td>{@link #SCREEN_BRIGHT_WAKE_LOCK}</td>
- *         <td>On</td> <td>Bright</td> <td>Off</td> 
+ *         <td>On</td> <td>Bright</td> <td>Off</td>
  *     </tr>
- *     
+ *
  *     <tr><td>{@link #FULL_WAKE_LOCK}</td>
- *         <td>On</td> <td>Bright</td> <td>Bright</td> 
+ *         <td>On</td> <td>Bright</td> <td>Bright</td>
  *     </tr>
  * </table>
  * </p><p>
@@ -85,13 +85,13 @@
  *         the illumination to remain on once it turns on (e.g. from user activity).  This flag
  *         will force the screen and/or keyboard to turn on immediately, when the WakeLock is
  *         acquired.  A typical use would be for notifications which are important for the user to
- *         see immediately.</td> 
+ *         see immediately.</td>
  *     </tr>
- *     
+ *
  *     <tr><td>{@link #ON_AFTER_RELEASE}</td>
  *         <td>If this flag is set, the user activity timer will be reset when the WakeLock is
- *         released, causing the illumination to remain on a bit longer.  This can be used to 
- *         reduce flicker if you are cycling between wake lock conditions.</td> 
+ *         released, causing the illumination to remain on a bit longer.  This can be used to
+ *         reduce flicker if you are cycling between wake lock conditions.</td>
  *     </tr>
  * </table>
  * <p>
@@ -479,6 +479,35 @@
     }
 
     /**
+     * Gets the minimum supported screen brightness setting for VR Mode.
+     * @hide
+     */
+    public int getMinimumScreenBrightnessForVrSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessForVrSettingMinimum);
+    }
+
+    /**
+     * Gets the maximum supported screen brightness setting for VR Mode.
+     * The screen may be allowed to become dimmer than this value but
+     * this is the maximum value that can be set by the user.
+     * @hide
+     */
+    public int getMaximumScreenBrightnessForVrSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessForVrSettingMaximum);
+    }
+
+    /**
+     * Gets the default screen brightness for VR setting.
+     * @hide
+     */
+    public int getDefaultScreenBrightnessForVrSetting() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault);
+    }
+
+    /**
      * Returns true if the twilight service should be used to adjust screen brightness
      * policy.  This setting is experimental and disabled by default.
      * @hide
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index 63ae9a9..23134cd 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -153,6 +153,15 @@
     public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
 
     /**
+     * Activity Action: Show the timers.
+     * <p>
+     * This action opens the timers page.
+     * </p>
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SHOW_TIMERS = "android.intent.action.SHOW_TIMERS";
+
+    /**
      * Activity Action: Show the alarms.
      * <p>
      * This action opens the alarms page.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cede9eb..2d4a9e9 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2889,6 +2889,15 @@
                 new InclusiveIntegerRangeValidator(0, 255);
 
         /**
+         * The screen backlight brightness between 0 and 255.
+         * @hide
+         */
+        public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr";
+
+        private static final Validator SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR =
+                new InclusiveIntegerRangeValidator(0, 255);
+
+        /**
          * Control whether to enable automatic brightness mode.
          */
         public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
@@ -3882,6 +3891,7 @@
             VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR);
             VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
             VALIDATORS.put(SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_VALIDATOR);
+            VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR);
             VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
             VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
             VALIDATORS.put(MUTE_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED_VALIDATOR);
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index a7941c7..c2e980c 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -17,8 +17,8 @@
 
 import static android.service.voice.VoiceInteractionSession.KEY_FLAGS;
 import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE;
-import static android.view.View.ASSIST_FLAG_SANITIZED_TEXT;
-import static android.view.View.ASSIST_FLAG_NON_SANITIZED_TEXT;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_FILL;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_SAVE;
 
 import android.annotation.SdkConstant;
 import android.app.Activity;
@@ -32,12 +32,15 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.FillResponse;
 
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.SomeArgs;
 
-// TODO(b/33197203): improve javadoc (class and methods)
+// 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.
 
 /**
  * Top-level service of the current auto-fill service for a given user.
@@ -58,40 +61,50 @@
     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
 
-    // Bundle keys.
-    /** @hide */
-    public static final String KEY_CALLBACK = "callback";
+    // Internal bundle keys.
+    /** @hide */ public static final String KEY_CALLBACK = "callback";
+    /** @hide */ public static final String KEY_SAVABLE_IDS = "savable_ids";
+
+    // Prefix for public bundle keys.
+    private static final String KEY_PREFIX = "android.service.autofill.extra.";
+
+    /**
+     * Key of the {@link Bundle} passed to methods such as
+     * {@link #onSaveRequest(AssistStructure, Bundle, CancellationSignal, SaveCallback)}
+     * containing the extras set by
+     * {@link android.view.autofill.FillResponse.Builder#setExtras(Bundle)}.
+     */
+    public static final String EXTRA_RESPONSE_EXTRAS = KEY_PREFIX + "RESPONSE_EXTRAS";
+
+    /**
+     * Key of the {@link Bundle} passed to methods such as
+     * {@link #onSaveRequest(AssistStructure, Bundle, CancellationSignal, SaveCallback)}
+     * containing the extras set by
+     * {@link android.view.autofill.Dataset.Builder#setExtras(Bundle)}.
+     */
+    public static final String EXTRA_DATASET_EXTRAS = KEY_PREFIX + "DATASET_EXTRAS";
 
     // Handler messages.
     private static final int MSG_CONNECT = 1;
     private static final int MSG_AUTO_FILL_ACTIVITY = 2;
     private static final int MSG_DISCONNECT = 3;
 
-    private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
-        @Override
-        public void send(int resultCode, Bundle resultData) throws RemoteException {
-            final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
-            final IBinder binder = resultData.getBinder(KEY_CALLBACK);
-            final int flags = resultData.getInt(KEY_FLAGS, 0);
+    private final IAutoFillService mInterface = new IAutoFillService.Stub() {
 
+        @Override
+        public void autoFill(AssistStructure structure, IAutoFillServerCallback callback,
+                Bundle extras, int flags) {
             mHandlerCaller
-                .obtainMessageIOO(MSG_AUTO_FILL_ACTIVITY, flags, structure, binder).sendToTarget();
+                    .obtainMessageIOOO(MSG_AUTO_FILL_ACTIVITY, flags, structure, extras, callback)
+                    .sendToTarget();
         }
 
-    };
-
-    private final IAutoFillService mInterface = new IAutoFillService.Stub() {
         @Override
         public void onConnected() {
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CONNECT));
         }
 
         @Override
-        public IResultReceiver getAssistReceiver() {
-            return mAssistReceiver;
-        }
-
-        @Override
         public void onDisconnected() {
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DISCONNECT));
         }
@@ -107,10 +120,11 @@
                     break;
                 } case MSG_AUTO_FILL_ACTIVITY: {
                     final SomeArgs args = (SomeArgs) msg.obj;
-                    final AssistStructure structure = (AssistStructure) args.arg1;
-                    final IBinder binder = (IBinder) args.arg2;
                     final int flags = msg.arg1;
-                    requestAutoFill(structure, flags, binder);
+                    final AssistStructure structure = (AssistStructure) args.arg1;
+                    final Bundle extras = (Bundle) args.arg2;
+                    final IAutoFillServerCallback callback = (IAutoFillServerCallback) args.arg3;
+                    requestAutoFill(callback, structure, extras, flags);
                     break;
                 } case MSG_DISCONNECT: {
                     onDisconnected();
@@ -146,7 +160,7 @@
     }
 
     /**
-     * Called when the Android System connects to service.
+     * Called when the Android system connects to service.
      *
      * <p>You should generally do initialization here rather than in {@link #onCreate}.
      */
@@ -155,12 +169,19 @@
     }
 
     /**
-     * Called when user requests service to auto-fill an {@link Activity}.
+     * Called by the Android system do decide if an {@link Activity} can be auto-filled by the
+     * service.
      *
-     * @param structure {@link Activity}'s view structure .
-     * @param data bundle with optional parameters (currently none) which is passed along on
-     * subsequent calls (so it can be used by the service to share data).
+     * <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 additional arguments set by the Android system (currently none)
+     * or data passed by the service on previous calls to fullfill other sections of this activity
+     * (see {@link FillResponse} Javadoc for examples of multiple-sections requests).
      * @param cancellationSignal signal for observing cancel requests.
+     * @param callback object used to notify the result of the request.
      */
     public abstract void onFillRequest(AssistStructure structure,
             Bundle data, CancellationSignal cancellationSignal, FillCallback callback);
@@ -168,29 +189,31 @@
     /**
      * 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(AutoFillId[])} or {@link SaveCallback#onFailure(CharSequence)})
+     * to notify the result of the request.
+     *
      * @param structure {@link Activity}'s view structure.
-     * @param data same bundle passed to
-     * {@link #onFillRequest(AssistStructure, Bundle, CancellationSignal, FillCallback)};
-     * might also contain with optional parameters (currently none).
+     * @param data bundle containing additional arguments set by the Android system (currently none)
+     * or data passed by the service in the {@link FillResponse} that originated this call.
      * @param cancellationSignal signal for observing cancel requests.
      * @param callback object used to notify the result of the request.
      */
     public abstract void onSaveRequest(AssistStructure structure,
             Bundle data, CancellationSignal cancellationSignal, SaveCallback callback);
 
-    private void requestAutoFill(AssistStructure structure, int flags, IBinder binder) {
-        // TODO(b/33197203): pass the Bundle received from mAssistReceiver instead?
-        final Bundle data = new Bundle();
+    private void requestAutoFill(IAutoFillServerCallback callback, AssistStructure structure,
+            Bundle data, int flags) {
         switch (flags) {
-            case ASSIST_FLAG_SANITIZED_TEXT:
-                final FillCallback fillCallback = new FillCallback(binder);
+            case AUTO_FILL_FLAG_TYPE_FILL:
+                final FillCallback fillCallback = new FillCallback(callback);
                 // TODO(b/33197203): hook up the cancelationSignal
                 onFillRequest(structure, data, new CancellationSignal(), fillCallback);
                 break;
-            case ASSIST_FLAG_NON_SANITIZED_TEXT:
-                final SaveCallback saveCallback = new SaveCallback(binder);
+            case AUTO_FILL_FLAG_TYPE_SAVE:
+                final SaveCallback saveCallback = new SaveCallback(callback);
                 // TODO(b/33197203): hook up the cancelationSignal
-                onSaveRequest(structure, null, new CancellationSignal(), saveCallback);
+                onSaveRequest(structure, data, new CancellationSignal(), saveCallback);
                 break;
             default:
                 Log.w(TAG, "invalid flag on requestAutoFill(): " + flags);
@@ -198,7 +221,7 @@
     }
 
     /**
-     * Called when the Android System disconnects from the service.
+     * Called when the Android system disconnects from the service.
      *
      * <p> At this point this service may no longer be an active {@link AutoFillService}.
      */
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 3284b90..5a9a9f6 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -18,19 +18,16 @@
 
 import static android.service.autofill.AutoFillService.DEBUG;
 
+import android.annotation.Nullable;
 import android.app.Activity;
-import android.app.assist.AssistStructure.ViewNode;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
-import android.util.SparseArray;
+import android.view.autofill.FillResponse;
 
 import com.android.internal.util.Preconditions;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 /**
  * Handles auto-fill requests from the {@link AutoFillService} into the {@link Activity} being
  * auto-filled.
@@ -39,40 +36,50 @@
 
     private static final String TAG = "FillCallback";
 
-    private final IAutoFillCallback mCallback;
+    private final IAutoFillServerCallback mCallback;
+
+    private boolean mReplied = false;
 
     /** @hide */
-    FillCallback(IBinder binder) {
-        mCallback = IAutoFillCallback.Stub.asInterface(binder);
+    FillCallback(IAutoFillServerCallback callback) {
+        mCallback = callback;
     }
 
     /**
-     * Auto-fills the {@link Activity}.
+     * Notifies the Android System that an
+     * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, FillCallback)}
+     * was successfully fulfilled by the service.
      *
-     * @throws RuntimeException if an error occurred while auto-filling it.
+     * @param response auto-fill information for that activity, or {@code null} when the activity
+     * cannot be auto-filled (for example, if it only contains read-only fields).
+     *
+     * @throws RuntimeException if an error occurred while calling the Android System.
      */
-    public void onSuccess(FillData data) {
-        if (DEBUG) Log.d(TAG, "onSuccess(): data=" + data);
+    public void onSuccess(@Nullable FillResponse response) {
+        if (DEBUG) Log.d(TAG, "onSuccess(): respose=" + response);
 
-        Preconditions.checkArgument(data != null, "data cannot be null");
+        checkNotRepliedYet();
 
         try {
-            mCallback.autofill(data.asList());
+            mCallback.showResponse(response);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
     }
 
     /**
-     * Notifies the {@link Activity} that the auto-fill request failed.
+     * Notifies the Android System that an
+     * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, FillCallback)}
+     * could not be fulfilled by the service.
      *
-     * @param message error message to be displayed.
+     * @param message error message to be displayed to the user.
      *
-     * @throws RuntimeException if an error occurred while notifying the activity.
+     * @throws RuntimeException if an error occurred while calling the Android System.
      */
     public void onFailure(CharSequence message) {
         if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
 
+        checkNotRepliedYet();
         Preconditions.checkArgument(message != null, "message cannot be null");
 
         try {
@@ -82,70 +89,9 @@
         }
     }
 
-    /**
-     * Data used to fill the fields of an {@link Activity}.
-     *
-     * <p>This class is immutable.
-     */
-    public static final class FillData {
-
-        private final List<FillableInputField> mList;
-
-        private FillData(Builder builder) {
-            final int size = builder.mFields.size();
-            final List<FillableInputField> list = new ArrayList<>(size);
-            for (int i = 0; i < size; i++) {
-                list.add(builder.mFields.valueAt(i));
-            }
-            mList = Collections.unmodifiableList(list);
-            // TODO: use FastImmutableArraySet or a similar structure instead?
-        }
-
-        /**
-         * Gets the response as a {@code List} so it can be used in a binder call.
-         */
-        List<FillableInputField> asList() {
-            return mList;
-        }
-
-        @Override
-        public String toString() {
-            return "[AutoFillResponse: " + mList + "]";
-        }
-
-        /**
-         * Builder for {@link FillData} objects.
-         *
-         * <p>Typical usage:
-         *
-         * <pre class="prettyprint">
-         * FillCallback.FillData data = new FillCallback.FillData.Builder()
-         *     .setTextField(id1, "value 1")
-         *     .setTextField(id2, "value 2")
-         *     .build()
-         * </pre>
-         */
-        public static class Builder {
-            private final SparseArray<FillableInputField> mFields = new SparseArray<>();
-
-            /**
-             * Auto-fills a text field.
-             *
-             * @param id view id as returned by {@link ViewNode#getAutoFillId()}.
-             * @param text text to be auto-filled.
-             * @return same builder so it can be chained.
-             */
-            public Builder setTextField(int id, String text) {
-                mFields.put(id, FillableInputField.forText(id, text));
-                return this;
-            }
-
-            /**
-             * Builds a new {@link FillData} instance.
-             */
-            public FillData build() {
-                return new FillData(this);
-            }
-        }
+    // There can be only one!!
+    private void checkNotRepliedYet() {
+        Preconditions.checkState(!mReplied, "already replied");
+        mReplied = true;
     }
 }
diff --git a/core/java/android/service/autofill/FillableInputField.java b/core/java/android/service/autofill/FillableInputField.java
deleted file mode 100644
index 62950b4..0000000
--- a/core/java/android/service/autofill/FillableInputField.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.autofill;
-
-import android.app.assist.AssistStructure.ViewNode;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents a view field that can be auto-filled.
- *
- * <p>Currently only text-fields are supported, so the value of the field can be obtained through
- * {@link #getValue()}.
- *
- * @hide
- */
-public final class FillableInputField implements Parcelable {
-
-    private final int mId;
-    private final String mValue;
-
-    private FillableInputField(int id, String value) {
-        mId = id;
-        mValue = value;
-    }
-
-    private FillableInputField(Parcel parcel) {
-        mId = parcel.readInt();
-        mValue = parcel.readString();
-    }
-
-    /**
-     * Gets the view id as returned by {@link ViewNode#getAutoFillId()}.
-     */
-    public int getId() {
-        return mId;
-    }
-
-    /**
-     * Gets the value of this field.
-     */
-    public String getValue() {
-        return mValue;
-
-    }
-
-    @Override
-    public String toString() {
-        return "[AutoFillField: " + mId + "=" + mValue + "]";
-    }
-
-    /**
-     * Creates an {@code AutoFillField} for a text field.
-     *
-     * @param id view id as returned by {@link ViewNode#getAutoFillId()}.
-     * @param text value to be auto-filled.
-     */
-    public static FillableInputField forText(int id, String text) {
-        return new FillableInputField(id, text);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeInt(mId);
-        parcel.writeString(mValue);
-    }
-
-    public static final Parcelable.Creator<FillableInputField> CREATOR =
-            new Parcelable.Creator<FillableInputField>() {
-        @Override
-        public FillableInputField createFromParcel(Parcel source) {
-            return new FillableInputField(source);
-        }
-
-        @Override
-        public FillableInputField[] newArray(int size) {
-            return new FillableInputField[size];
-        }
-    };
-}
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/service/autofill/IAutoFillAppCallback.aidl
similarity index 85%
rename from core/java/android/service/autofill/IAutoFillCallback.aidl
rename to core/java/android/service/autofill/IAutoFillAppCallback.aidl
index d6d4f39..629b1f0 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/service/autofill/IAutoFillAppCallback.aidl
@@ -18,10 +18,11 @@
 
 import java.util.List;
 
+import android.view.autofill.Dataset;
+
 /**
  * @hide
  */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
+oneway interface IAutoFillAppCallback {
+    void autoFill(in Dataset dataset);
 }
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
index f1251c0..f8ae57b 100644
--- a/core/java/android/service/autofill/IAutoFillManagerService.aidl
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -24,6 +24,5 @@
  * {@hide}
  */
 oneway interface IAutoFillManagerService {
-
-    void requestAutoFill(IBinder activityToken, int userId, int flags);
+    void requestAutoFill(IBinder activityToken, int userId, in Bundle extras, int flags);
 }
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/service/autofill/IAutoFillServerCallback.aidl
similarity index 76%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/service/autofill/IAutoFillServerCallback.aidl
index d6d4f39..9d58c99 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/service/autofill/IAutoFillServerCallback.aidl
@@ -18,10 +18,14 @@
 
 import java.util.List;
 
+import android.view.autofill.AutoFillId;
+import android.view.autofill.FillResponse;
+
 /**
  * @hide
  */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
+oneway interface IAutoFillServerCallback {
+    void showResponse(in FillResponse response);
     void showError(String message);
+    void highlightSavedFields(in AutoFillId[] ids);
 }
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index bb122e5..a1f22bf 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -18,14 +18,15 @@
 
 import android.app.assist.AssistStructure;
 import android.os.Bundle;
-import android.service.autofill.IAutoFillCallback;
+import android.service.autofill.IAutoFillServerCallback;
 import com.android.internal.os.IResultReceiver;
 
 /**
  * @hide
  */
-interface IAutoFillService {
-    oneway void onConnected();
-    oneway void onDisconnected();
-    IResultReceiver getAssistReceiver();
+oneway interface IAutoFillService {
+    void autoFill(in AssistStructure structure, in IAutoFillServerCallback callback,
+                  in Bundle extras, int flags);
+    void onConnected();
+    void onDisconnected();
 }
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index 4dc7392..627d74c 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -20,9 +20,11 @@
 
 import android.app.Activity;
 import android.app.assist.AssistStructure.ViewNode;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.autofill.AutoFillId;
 
 import com.android.internal.util.Preconditions;
 
@@ -34,41 +36,53 @@
 
     private static final String TAG = "SaveCallback";
 
-    private final IAutoFillCallback mCallback;
+    private final IAutoFillServerCallback mCallback;
+
+    private boolean mReplied = false;
 
     /** @hide */
-    SaveCallback(IBinder binder) {
-        mCallback = IAutoFillCallback.Stub.asInterface(binder);
+    SaveCallback(IAutoFillServerCallback callback) {
+        mCallback = callback;
     }
 
     /**
-     * Notifies the {@link Activity} that the save request succeeded.
+     * Notifies the Android System that an
+     * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, SaveCallback)}
+     * was successfully fulfilled by the service.
      *
      * @param ids ids ({@link ViewNode#getAutoFillId()}) of the fields that were saved.
      *
-     * @throws RuntimeException if an error occurred while saving the data.
+     * @throws RuntimeException if an error occurred while calling the Android System.
      */
-    public void onSuccess(int[] ids) {
+    public void onSuccess(AutoFillId[] ids) {
+        if (DEBUG) Log.d(TAG, "onSuccess(): ids=" + ((ids == null) ? "null" : ids.length));
+
         Preconditions.checkArgument(ids != null, "ids cannot be null");
+        checkNotRepliedYet();
 
         Preconditions.checkArgument(ids.length > 0, "ids cannot be empty");
 
-        if (DEBUG) Log.d(TAG, "onSuccess(): ids=" + ids.length);
-
-        // TODO(b/33197203): display which ids were saved
+        try {
+            mCallback.highlightSavedFields(ids);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
     }
 
     /**
-     * Notifies the {@link Activity} that the save request failed.
+     * Notifies the Android System that an
+     * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, SaveCallback)}
+     * could not be fulfilled by the service.
      *
-     * @param message error message to be displayed.
+     * @param message error message to be displayed to the user.
      *
-     * @throws RuntimeException if an error occurred while notifying the activity.
+     * @throws RuntimeException if an error occurred while calling the Android System.
      */
     public void onFailure(CharSequence message) {
         if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
 
         Preconditions.checkArgument(message != null, "message cannot be null");
+        checkNotRepliedYet();
 
         try {
             mCallback.showError(message.toString());
@@ -76,4 +90,10 @@
             e.rethrowAsRuntimeException();
         }
     }
+
+    // There can be only one!!
+    private void checkNotRepliedYet() {
+        Preconditions.checkState(!mReplied, "already replied");
+        mReplied = true;
+    }
 }
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 9ac8996..1e9deeb 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -85,7 +85,7 @@
         this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                 spacingmult, spacingadd, includepad,
                 StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE,
-                ellipsize, ellipsizedWidth);
+                false /* justify */, ellipsize, ellipsizedWidth);
     }
 
     /**
@@ -102,7 +102,8 @@
                          int width, Alignment align, TextDirectionHeuristic textDir,
                          float spacingmult, float spacingadd,
                          boolean includepad, int breakStrategy, int hyphenationFrequency,
-                         TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
+                         boolean justify, TextUtils.TruncateAt ellipsize,
+                         int ellipsizedWidth) {
         super((ellipsize == null)
                 ? display
                 : (display instanceof Spanned)
@@ -127,6 +128,7 @@
 
         mIncludePad = includepad;
         mBreakStrategy = breakStrategy;
+        mJustify = justify;
         mHyphenationFrequency = hyphenationFrequency;
 
         /*
@@ -300,7 +302,8 @@
                 .setEllipsizedWidth(mEllipsizedWidth)
                 .setEllipsize(mEllipsizeAt)
                 .setBreakStrategy(mBreakStrategy)
-                .setHyphenationFrequency(mHyphenationFrequency);
+                .setHyphenationFrequency(mHyphenationFrequency)
+                .setJustify(mJustify);
         reflowed.generate(b, false, true);
         int n = reflowed.getLineCount();
         // If the new layout has a blank line at the end, but it is not
@@ -808,6 +811,7 @@
     private TextUtils.TruncateAt mEllipsizeAt;
     private int mBreakStrategy;
     private int mHyphenationFrequency;
+    private boolean mJustify;
 
     private PackedIntVector mInts;
     private PackedObjectVector<Directions> mObjects;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 3cb81b0..2fc12d3 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -218,6 +218,11 @@
         mTextDir = textDir;
     }
 
+    /** @hide */
+    protected void setJustify(boolean justify) {
+        mJustify = justify;
+    }
+
     /**
      * Replace constructor properties of this Layout with new ones.  Be careful.
      */
@@ -266,6 +271,99 @@
         drawText(canvas, firstLine, lastLine);
     }
 
+    private boolean isJustificationRequired(int lineNum) {
+        if (!mJustify) return false;
+        final int lineEnd = getLineEnd(lineNum);
+        return lineEnd < mText.length() && mText.charAt(lineEnd - 1) != '\n';
+    }
+
+    private float getJustifyWidth(int lineNum) {
+        Alignment paraAlign = mAlignment;
+        TabStops tabStops = null;
+        boolean tabStopsIsInitialized = false;
+
+        int left = 0;
+        int right = mWidth;
+
+        final int dir = getParagraphDirection(lineNum);
+
+        ParagraphStyle[] spans = NO_PARA_SPANS;
+        if (mSpannedText) {
+            Spanned sp = (Spanned) mText;
+            final int start = getLineStart(lineNum);
+
+            final boolean isFirstParaLine = (start == 0 || mText.charAt(start - 1) == '\n');
+
+            if (isFirstParaLine) {
+                final int spanEnd = sp.nextSpanTransition(start, mText.length(),
+                        ParagraphStyle.class);
+                spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
+
+                for (int n = spans.length - 1; n >= 0; n--) {
+                    if (spans[n] instanceof AlignmentSpan) {
+                        paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
+                        break;
+                    }
+                }
+            }
+
+            final int length = spans.length;
+            boolean useFirstLineMargin = isFirstParaLine;
+            for (int n = 0; n < length; n++) {
+                if (spans[n] instanceof LeadingMarginSpan2) {
+                    int count = ((LeadingMarginSpan2) spans[n]).getLeadingMarginLineCount();
+                    int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
+                    if (lineNum < startLine + count) {
+                        useFirstLineMargin = true;
+                        break;
+                    }
+                }
+            }
+            for (int n = 0; n < length; n++) {
+                if (spans[n] instanceof LeadingMarginSpan) {
+                    LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
+                    if (dir == DIR_RIGHT_TO_LEFT) {
+                        right -= margin.getLeadingMargin(useFirstLineMargin);
+                    } else {
+                        left += margin.getLeadingMargin(useFirstLineMargin);
+                    }
+                }
+            }
+        }
+
+        if (getLineContainsTab(lineNum)) {
+            tabStops = new TabStops(TAB_INCREMENT, spans);
+        }
+
+        final Alignment align;
+        if (paraAlign == Alignment.ALIGN_LEFT) {
+            align = (dir == DIR_LEFT_TO_RIGHT) ?  Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
+        } else if (paraAlign == Alignment.ALIGN_RIGHT) {
+            align = (dir == DIR_LEFT_TO_RIGHT) ?  Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
+        } else {
+            align = paraAlign;
+        }
+
+        final int indentWidth;
+        if (align == Alignment.ALIGN_NORMAL) {
+            if (dir == DIR_LEFT_TO_RIGHT) {
+                indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
+            } else {
+                indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
+            }
+        } else if (align == Alignment.ALIGN_OPPOSITE) {
+            if (dir == DIR_LEFT_TO_RIGHT) {
+                indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
+            } else {
+                indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
+            }
+        } else { // Alignment.ALIGN_CENTER
+            indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
+        }
+
+        return right - left - indentWidth;
+    }
+
     /**
      * @hide
      */
@@ -274,7 +372,7 @@
         int previousLineEnd = getLineStart(firstLine);
         ParagraphStyle[] spans = NO_PARA_SPANS;
         int spanEnd = 0;
-        TextPaint paint = mPaint;
+        final TextPaint paint = mPaint;
         CharSequence buf = mText;
 
         Alignment paraAlign = mAlignment;
@@ -288,6 +386,7 @@
         for (int lineNum = firstLine; lineNum <= lastLine; lineNum++) {
             int start = previousLineEnd;
             previousLineEnd = getLineStart(lineNum + 1);
+            final boolean justify = isJustificationRequired(lineNum);
             int end = getLineVisibleEnd(lineNum, start, previousLineEnd);
 
             int ltop = previousLineBottom;
@@ -386,34 +485,42 @@
             }
 
             int x;
+            final int indentWidth;
             if (align == Alignment.ALIGN_NORMAL) {
                 if (dir == DIR_LEFT_TO_RIGHT) {
-                    x = left + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
+                    indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
+                    x = left + indentWidth;
                 } else {
-                    x = right + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
+                    indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
+                    x = right - indentWidth;
                 }
             } else {
                 int max = (int)getLineExtent(lineNum, tabStops, false);
                 if (align == Alignment.ALIGN_OPPOSITE) {
                     if (dir == DIR_LEFT_TO_RIGHT) {
-                        x = right - max + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
+                        indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
+                        x = right - max - indentWidth;
                     } else {
-                        x = left - max + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
+                        indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
+                        x = left - max + indentWidth;
                     }
                 } else { // Alignment.ALIGN_CENTER
+                    indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
                     max = max & ~1;
-                    x = ((right + left - max) >> 1) +
-                            getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
+                    x = ((right + left - max) >> 1) + indentWidth;
                 }
             }
 
             paint.setHyphenEdit(getHyphen(lineNum));
             Directions directions = getLineDirections(lineNum);
-            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab) {
+            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab && !justify) {
                 // XXX: assumes there's nothing additional to be done
                 canvas.drawText(buf, start, end, x, lbaseline, paint);
             } else {
                 tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops);
+                if (justify) {
+                    tl.justify(right - left - indentWidth);
+                }
                 tl.draw(canvas, x, ltop, lbaseline, lbottom);
             }
             paint.setHyphenEdit(0);
@@ -1094,6 +1201,9 @@
         TextLine tl = TextLine.obtain();
         mPaint.setHyphenEdit(getHyphen(line));
         tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops);
+        if (isJustificationRequired(line)) {
+            tl.justify(getJustifyWidth(line));
+        }
         float width = tl.metrics(null);
         mPaint.setHyphenEdit(0);
         TextLine.recycle(tl);
@@ -1118,6 +1228,9 @@
         TextLine tl = TextLine.obtain();
         mPaint.setHyphenEdit(getHyphen(line));
         tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops);
+        if (isJustificationRequired(line)) {
+            tl.justify(getJustifyWidth(line));
+        }
         float width = tl.metrics(null);
         mPaint.setHyphenEdit(0);
         TextLine.recycle(tl);
@@ -1303,10 +1416,7 @@
                 return end - 1;
             }
 
-            // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace()
-            if (!(ch == ' ' || ch == '\t' || ch == 0x1680 ||
-                    (0x2000 <= ch && ch <= 0x200A && ch != 0x2007) ||
-                    ch == 0x205F || ch == 0x3000)) {
+            if (!TextLine.isLineEndSpace(ch)) {
                 break;
             }
 
@@ -2086,6 +2196,7 @@
     private boolean mSpannedText;
     private TextDirectionHeuristic mTextDir;
     private SpanSet<LineBackgroundSpan> mLineBackgroundSpans;
+    private boolean mJustify;
 
     public static final int DIR_LEFT_TO_RIGHT = 1;
     public static final int DIR_RIGHT_TO_LEFT = -1;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 081be3a..cb5b073 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -94,6 +94,7 @@
             b.mMaxLines = Integer.MAX_VALUE;
             b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
             b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
+            b.mJustify = false;
 
             b.mMeasuredText = MeasuredText.obtain();
             return b;
@@ -320,6 +321,17 @@
         }
 
         /**
+         * Enables or disables paragraph justification. The default value is disabled (false).
+         *
+         * @param justify true for enabling and false for disabling paragraph justification.
+         * @return this builder, useful for chaining.
+         */
+        public Builder setJustify(boolean justify) {
+            mJustify = justify;
+            return this;
+        }
+
+        /**
          * Measurement and break iteration is done in native code. The protocol for using
          * the native code is as follows.
          *
@@ -404,6 +416,7 @@
         int mHyphenationFrequency;
         int[] mLeftIndents;
         int[] mRightIndents;
+        boolean mJustify;
 
         Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
 
@@ -557,6 +570,7 @@
 
         mLeftIndents = b.mLeftIndents;
         mRightIndents = b.mRightIndents;
+        setJustify(b.mJustify);
 
         generate(b, b.mIncludePad, b.mIncludePad);
     }
@@ -676,7 +690,8 @@
 
             nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart,
                     firstWidth, firstWidthLineCount, restWidth,
-                    variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency);
+                    variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency,
+                    b.mJustify);
             if (mLeftIndents != null || mRightIndents != null) {
                 // TODO(raph) performance: it would be better to do this once per layout rather
                 // than once per paragraph, but that would require a change to the native
@@ -1284,7 +1299,8 @@
     // Set up paragraph text and settings; done as one big method to minimize jni crossings
     private static native void nSetupParagraph(long nativePtr, char[] text, int length,
             float firstWidth, int firstWidthLineCount, float restWidth,
-            int[] variableTabStops, int defaultTabStop, int breakStrategy, int hyphenationFrequency);
+            int[] variableTabStops, int defaultTabStop, int breakStrategy, int hyphenationFrequency,
+            boolean isJustified);
 
     private static native float nAddStyleRun(long nativePtr, long nativePaint,
             long nativeTypeface, int start, int end, boolean isRtl);
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index c411860..fcff9a2 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -54,6 +54,10 @@
     private char[] mChars;
     private boolean mCharsValid;
     private Spanned mSpanned;
+
+    // Additional width of whitespace for justification. This value is per whitespace, thus
+    // the line width will increase by mAddedWidth x (number of stretchable whitespaces).
+    private float mAddedWidth;
     private final TextPaint mWorkPaint = new TextPaint();
     private final SpanSet<MetricAffectingSpan> mMetricAffectingSpanSpanSet =
             new SpanSet<MetricAffectingSpan>(MetricAffectingSpan.class);
@@ -177,6 +181,25 @@
             }
         }
         mTabs = tabStops;
+        mAddedWidth = 0;
+    }
+
+    /**
+     * Justify the line to the given width.
+     */
+    void justify(float justifyWidth) {
+        int end = mLen;
+        while (end > 0 && isLineEndSpace(mText.charAt(mStart + end - 1))) {
+            end--;
+        }
+        final int spaces = countStretchableSpaces(0, end);
+        if (spaces == 0) {
+            // There are no stretchable spaces, so we can't help the justification by adding any
+            // width.
+            return;
+        }
+        final float width = Math.abs(measure(end, false, null));
+        mAddedWidth = (justifyWidth - width) / spaces;
     }
 
     /**
@@ -595,6 +618,7 @@
 
         TextPaint wp = mWorkPaint;
         wp.set(mPaint);
+        wp.setWordSpacing(mAddedWidth);
 
         int spanStart = runStart;
         int spanLimit;
@@ -695,6 +719,7 @@
             Canvas c, float x, int top, int y, int bottom,
             FontMetricsInt fmi, boolean needWidth, int offset) {
 
+        wp.setWordSpacing(mAddedWidth);
         // Get metrics first (even for empty strings or "0" width runs)
         if (fmi != null) {
             expandMetricsFromPaint(fmi, wp);
@@ -981,5 +1006,34 @@
         return TabStops.nextDefaultStop(h, TAB_INCREMENT);
     }
 
+    private boolean isStretchableWhitespace(int ch) {
+        // TODO: Support other stretchable whitespace. (Bug: 34013491)
+        return ch == 0x0020 || ch == 0x00A0;
+    }
+
+    private int nextStretchableSpace(int start, int end) {
+        for (int i = start; i < end; i++) {
+            final char c = mCharsValid ? mChars[i] : mText.charAt(i + mStart);
+            if (isStretchableWhitespace(c)) return i;
+        }
+        return end;
+    }
+
+    /* Return the number of spaces in the text line, for the purpose of justification */
+    private int countStretchableSpaces(int start, int end) {
+        int count = 0;
+        for (int i = start; i < end; i = nextStretchableSpace(i + 1, end)) {
+            count++;
+        }
+        return count;
+    }
+
+    // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace()
+    public static boolean isLineEndSpace(char ch) {
+        return ch == ' ' || ch == '\t' || ch == 0x1680
+                || (0x2000 <= ch && ch <= 0x200A && ch != 0x2007)
+                || ch == 0x205F || ch == 0x3000;
+    }
+
     private static final int TAB_INCREMENT = 20;
 }
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 58bc9a7..bb952ab 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -29,6 +29,8 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.text.style.AbsoluteSizeSpan;
+import android.text.style.AccessibilityClickableSpan;
+import android.text.style.AccessibilityURLSpan;
 import android.text.style.AlignmentSpan;
 import android.text.style.BackgroundColorSpan;
 import android.text.style.BulletSpan;
@@ -621,7 +623,11 @@
     /** @hide */
     public static final int TTS_SPAN = 24;
     /** @hide */
-    public static final int LAST_SPAN = TTS_SPAN;
+    public static final int ACCESSIBILITY_CLICKABLE_SPAN = 25;
+    /** @hide */
+    public static final int ACCESSIBILITY_URL_SPAN = 26;
+    /** @hide */
+    public static final int LAST_SPAN = ACCESSIBILITY_URL_SPAN;
 
     /**
      * Flatten a CharSequence and whatever styles can be copied across processes
@@ -803,6 +809,14 @@
                     readSpan(p, sp, new TtsSpan(p));
                     break;
 
+                case ACCESSIBILITY_CLICKABLE_SPAN:
+                    readSpan(p, sp, new AccessibilityClickableSpan(p));
+                    break;
+
+                case ACCESSIBILITY_URL_SPAN:
+                    readSpan(p, sp, new AccessibilityURLSpan(p));
+                    break;
+
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
diff --git a/core/java/android/text/style/AccessibilityClickableSpan.java b/core/java/android/text/style/AccessibilityClickableSpan.java
new file mode 100644
index 0000000..9c305ff
--- /dev/null
+++ b/core/java/android/text/style/AccessibilityClickableSpan.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.style;
+
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.ParcelableSpan;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.internal.R;
+
+import java.lang.ref.WeakReference;
+
+
+/**
+ * {@link ClickableSpan} cannot be parceled, but accessibility services need to be able to cause
+ * their callback handlers to be called. This class serves as a parcelable placeholder for the
+ * real spans.
+ *
+ * This span is also passed back to an app's process when an accessibility service tries to click
+ * it. It contains enough information to track down the original clickable span so it can be
+ * called.
+ *
+ * @hide
+ */
+public class AccessibilityClickableSpan extends ClickableSpan
+        implements ParcelableSpan {
+    // The id of the span this one replaces
+    private final int mOriginalClickableSpanId;
+
+    // Only retain a weak reference to the node to avoid referencing cycles that could create memory
+    // leaks.
+    private WeakReference<AccessibilityNodeInfo> mAccessibilityNodeInfoRef;
+
+
+    /**
+     * @param originalClickableSpanId The id of the span this one replaces
+     */
+    public AccessibilityClickableSpan(int originalClickableSpanId) {
+        mOriginalClickableSpanId = originalClickableSpanId;
+    }
+
+    public AccessibilityClickableSpan(Parcel p) {
+        mOriginalClickableSpanId = p.readInt();
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return getSpanTypeIdInternal();
+    }
+
+    @Override
+    public int getSpanTypeIdInternal() {
+        return TextUtils.ACCESSIBILITY_CLICKABLE_SPAN;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeToParcelInternal(dest, flags);
+    }
+
+    @Override
+    public void writeToParcelInternal(Parcel dest, int flags) {
+        dest.writeInt(mOriginalClickableSpanId);
+    }
+
+    /**
+     * Find the ClickableSpan that matches the one used to create this object.
+     *
+     * @param text The text that contains the original ClickableSpan.
+     * @return The ClickableSpan that matches this object, or {@code null} if no such object
+     * can be found.
+     */
+    public ClickableSpan findClickableSpan(CharSequence text) {
+        if (!(text instanceof Spanned)) {
+            return null;
+        }
+        Spanned sp = (Spanned) text;
+        ClickableSpan[] os = sp.getSpans(0, text.length(), ClickableSpan.class);
+        for (int i = 0; i < os.length; i++) {
+            if (os[i].getId() == mOriginalClickableSpanId) {
+                return os[i];
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Set the accessibilityNodeInfo that this placeholder belongs to. This node is not
+     * included in the parceling logic, and must be set to allow the onClick handler to function.
+     *
+     * @param accessibilityNodeInfo The info this span is part of
+     */
+    public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) {
+        mAccessibilityNodeInfoRef = new WeakReference<>(accessibilityNodeInfo);
+    }
+
+    /**
+     * Perform the click from an accessibility service. Will not work unless
+     * setAccessibilityNodeInfo is called with a properly initialized node.
+     *
+     * @param unused This argument is required by the superclass but is unused. The real view will
+     * be determined by the AccessibilityNodeInfo.
+     */
+    @Override
+    public void onClick(View unused) {
+        if (mAccessibilityNodeInfoRef == null) {
+            return;
+        }
+        AccessibilityNodeInfo info = mAccessibilityNodeInfoRef.get();
+        if (info == null) {
+            return;
+        }
+        Bundle arguments = new Bundle();
+        arguments.putParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN, this);
+
+        info.performAction(R.id.accessibilityActionClickOnClickableSpan, arguments);
+    }
+
+    public static final Parcelable.Creator<AccessibilityClickableSpan> CREATOR =
+            new Parcelable.Creator<AccessibilityClickableSpan>() {
+                @Override
+                public AccessibilityClickableSpan createFromParcel(Parcel parcel) {
+                    return new AccessibilityClickableSpan(parcel);
+                }
+
+                @Override
+                public AccessibilityClickableSpan[] newArray(int size) {
+                    return new AccessibilityClickableSpan[size];
+                }
+            };
+}
diff --git a/core/java/android/text/style/AccessibilityURLSpan.java b/core/java/android/text/style/AccessibilityURLSpan.java
new file mode 100644
index 0000000..0147009
--- /dev/null
+++ b/core/java/android/text/style/AccessibilityURLSpan.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.style;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+/**
+ * URLSpan's onClick method does not work from an accessibility service. This version of it does.
+ * It is used to replace URLSpans in {@link AccessibilityNodeInfo#setText(CharSequence)}
+ * @hide
+ */
+public class AccessibilityURLSpan extends URLSpan implements Parcelable {
+    final AccessibilityClickableSpan mAccessibilityClickableSpan;
+
+    /**
+     * @param spanToReplace The original span
+     */
+    public AccessibilityURLSpan(URLSpan spanToReplace) {
+        super(spanToReplace.getURL());
+        mAccessibilityClickableSpan =
+                new AccessibilityClickableSpan(spanToReplace.getId());
+    }
+
+    public AccessibilityURLSpan(Parcel p) {
+        super(p);
+        mAccessibilityClickableSpan = new AccessibilityClickableSpan(p);
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return getSpanTypeIdInternal();
+    }
+
+    @Override
+    public int getSpanTypeIdInternal() {
+        return TextUtils.ACCESSIBILITY_URL_SPAN;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeToParcelInternal(dest, flags);
+    }
+
+    @Override
+    public void writeToParcelInternal(Parcel dest, int flags) {
+        super.writeToParcelInternal(dest, flags);
+        mAccessibilityClickableSpan.writeToParcel(dest, flags);
+    }
+
+    @Override
+    public void onClick(View unused) {
+        mAccessibilityClickableSpan.onClick(unused);
+    }
+
+    /**
+     * Delegated to AccessibilityClickableSpan
+     * @param accessibilityNodeInfo
+     */
+    public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) {
+        mAccessibilityClickableSpan.setAccessibilityNodeInfo(accessibilityNodeInfo);
+    }
+}
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
index 989ef54..a183427 100644
--- a/core/java/android/text/style/ClickableSpan.java
+++ b/core/java/android/text/style/ClickableSpan.java
@@ -26,12 +26,15 @@
  * be called.
  */
 public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
+    private static int sIdCounter = 0;
+
+    private int mId = sIdCounter++;
 
     /**
      * Performs the click action associated with this span.
      */
     public abstract void onClick(View widget);
-   
+
     /**
      * Makes the text underlined and in the link color.
      */
@@ -40,4 +43,14 @@
         ds.setColor(ds.linkColor);
         ds.setUnderlineText(true);
     }
+
+    /**
+     * Get the unique ID for this span.
+     *
+     * @return The unique ID.
+     * @hide
+     */
+    public int getId() {
+        return mId;
+    }
 }
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 99f6c2a9..79d16fb 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -59,7 +59,7 @@
         private Exception mLastWtf;
 
         // Layout of event log entry received from Android logger.
-        //  see system/core/include/log/logger.h
+        //  see system/core/include/log/log.h
         private static final int LENGTH_OFFSET = 0;
         private static final int HEADER_SIZE_OFFSET = 2;
         private static final int PROCESS_OFFSET = 4;
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index c7b1d03..13ee48e 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN;
+
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -24,8 +26,12 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
+import android.text.TextUtils;
+import android.text.style.AccessibilityClickableSpan;
+import android.text.style.ClickableSpan;
 import android.util.LongSparseArray;
 import android.view.View.AttachInfo;
 import android.view.accessibility.AccessibilityInteractionClient;
@@ -33,6 +39,7 @@
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
+import com.android.internal.R;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.Predicate;
 
@@ -655,17 +662,23 @@
                 target = mViewRootImpl.mView;
             }
             if (target != null && isShown(target)) {
-                AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
-                if (provider != null) {
-                    if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                        succeeded = provider.performAction(virtualDescendantId, action,
-                                arguments);
-                    } else {
-                        succeeded = provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID,
-                                action, arguments);
+                if (action == R.id.accessibilityActionClickOnClickableSpan) {
+                    // Handle this hidden action separately
+                    succeeded = handleClickableSpanActionUiThread(
+                            target, virtualDescendantId, arguments);
+                } else {
+                    AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
+                    if (provider != null) {
+                        if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                            succeeded = provider.performAction(virtualDescendantId, action,
+                                    arguments);
+                        } else {
+                            succeeded = provider.performAction(
+                                    AccessibilityNodeProvider.HOST_VIEW_ID, action, arguments);
+                        }
+                    } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+                        succeeded = target.performAccessibilityAction(action, arguments);
                     }
-                } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                    succeeded = target.performAccessibilityAction(action, arguments);
                 }
             }
         } finally {
@@ -816,6 +829,37 @@
         return (appScale != 1.0f || (spec != null && !spec.isNop()));
     }
 
+    private boolean handleClickableSpanActionUiThread(
+            View view, int virtualDescendantId, Bundle arguments) {
+        Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN);
+        if (!(span instanceof AccessibilityClickableSpan)) {
+            return false;
+        }
+
+        // Find the original ClickableSpan if it's still on the screen
+        AccessibilityNodeInfo infoWithSpan = null;
+        AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+        if (provider != null) {
+            int idForNode = (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
+                    ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualDescendantId;
+            infoWithSpan = provider.createAccessibilityNodeInfo(idForNode);
+        } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+            infoWithSpan = view.createAccessibilityNodeInfo();
+        }
+        if (infoWithSpan == null) {
+            return false;
+        }
+
+        // Click on the corresponding span
+        ClickableSpan clickableSpan = ((AccessibilityClickableSpan) span).findClickableSpan(
+                infoWithSpan.getOriginalText());
+        if (clickableSpan != null) {
+            clickableSpan.onClick(view);
+            return true;
+        }
+        return false;
+    }
+
     /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
      * querying window content. It is responsible to prefetch a batch of
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 3beb00f..b37ea8e 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -282,6 +282,15 @@
      */
     public static final int STATE_DOZE_SUSPEND = 4;
 
+    /**
+     * Display state: The display is on and optimized for VR mode.
+     *
+     * @see #getState
+     * @see android.os.PowerManager#isInteractive
+     * @hide
+     */
+    public static final int STATE_VR = 5;
+
     /* The color mode constants defined below must be kept in sync with the ones in
      * system/graphics.h */
 
@@ -866,7 +875,8 @@
      * Gets the state of the display, such as whether it is on or off.
      *
      * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
-     * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or {@link #STATE_UNKNOWN}.
+     * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or
+     * {@link #STATE_UNKNOWN}.
      */
     public int getState() {
         synchronized (this) {
@@ -982,6 +992,8 @@
                 return "DOZE";
             case STATE_DOZE_SUSPEND:
                 return "DOZE_SUSPEND";
+            case STATE_VR:
+                return "VR";
             default:
                 return Integer.toString(state);
         }
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index a3e8312..2fd2e96 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -116,9 +116,34 @@
          * size before it has been correctly drawn that way).  This will
          * typically be preceeded by a call to {@link #surfaceChanged}.
          *
+         * As of O, {@link #surfaceRedrawNeededAsync} may be implemented
+         * to provide a non-blocking implementation. If {@link #surfaceRedrawNeededAsync}
+         * is not implemented, then this will be called instead.
+         *
          * @param holder The SurfaceHolder whose surface has changed.
          */
-        public void surfaceRedrawNeeded(SurfaceHolder holder);
+        void surfaceRedrawNeeded(SurfaceHolder holder);
+
+        /**
+         * An alternative to surfaceRedrawNeeded where it is not required to block
+         * until the redraw is complete. You should initiate the redraw, and return,
+         * later invoking drawingFinished when your redraw is complete.
+         *
+         * This can be useful to avoid blocking your main application thread on rendering.
+         *
+         * As of O, if this is implemented {@link #surfaceRedrawNeeded} will not be called.
+         * However it is still recommended to implement {@link #surfaceRedrawNeeded} for
+         * compatibility with older versions of the platform.
+         *
+         * @param holder The SurfaceHolder which needs redrawing.
+         * @param drawingFinished A runnable to signal completion. This may be invoked
+         * from any thread.
+         *
+         */
+        default void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable drawingFinished) {
+            surfaceRedrawNeeded(holder);
+            drawingFinished.run();
+        }
     }
 
     /**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index d46910c..018be86 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -33,6 +33,7 @@
 import android.util.Log;
 
 import com.android.internal.view.BaseIWindow;
+import com.android.internal.view.SurfaceCallbackHelper;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -639,21 +640,13 @@
                             if (callbacks == null) {
                                 callbacks = getSurfaceCallbacks();
                             }
-                            for (SurfaceHolder.Callback c : callbacks) {
-                                if (c instanceof SurfaceHolder.Callback2) {
-                                    ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
-                                            mSurfaceHolder);
-                                }
-                            }
+                            SurfaceCallbackHelper sch =
+                                    new SurfaceCallbackHelper(mSession, mWindow);
+                            sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
                         }
                     }
                 } finally {
                     mIsCreating = false;
-                    if (redrawNeeded) {
-                        if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
-                                + "finishedDrawing");
-                        mSession.finishDrawing(mWindow);
-                    }
                     mSession.performDeferredDestroy(mWindow);
                 }
             } catch (RemoteException ex) {
@@ -876,7 +869,6 @@
     }
 
     private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
-
         private static final String LOG_TAG = "SurfaceHolder";
 
         @Override
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 5012215..f3ebcb4 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -28,7 +28,6 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Trace;
 import android.util.Log;
@@ -72,17 +71,6 @@
     private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
 
     /**
-     * System property used to enable or disable dirty regions invalidation.
-     * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
-     * The default value of this property is assumed to be true.
-     *
-     * Possible values:
-     * "true", to enable partial invalidates
-     * "false", to disable partial invalidates
-     */
-    static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
-
-    /**
      * System property used to enable or disable threaded rendering profiling.
      * The default value of this property is assumed to be false.
      *
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ecc0f2d..aedd0df 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -39,6 +39,7 @@
 import android.annotation.Size;
 import android.annotation.TestApi;
 import android.annotation.UiThread;
+import android.app.Application.OnProvideAssistDataListener;
 import android.content.ClipData;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -103,6 +104,9 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillValue;
+import android.view.autofill.VirtualViewDelegate;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
@@ -3313,7 +3317,9 @@
         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
     }, formatToHexString = true)
-    int mPrivateFlags;
+
+    /* @hide */
+    public int mPrivateFlags;
     int mPrivateFlags2;
     int mPrivateFlags3;
 
@@ -4023,18 +4029,34 @@
 
 
     /**
-     * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should not contain
-     * PII (Personally Identifiable Information).
+     * Set when a request was made to decide if views in an {@link android.app.Activity} can be
+     * auto-filled by an {@link android.service.autofill.AutoFillService}.
+     *
+     * <p>Since this request is made without a explicit user consent, the resulting
+     * {@link android.app.assist.AssistStructure} should not contain any PII
+     * (Personally Identifiable Information).
+     *
+     * <p>Examples:
+     * <ul>
+     * <li>{@link android.widget.TextView} texts should only be included when they were set by
+     * static resources.
+     * <li>{@link android.webkit.WebView} virtual children should be restricted to a subset of
+     * input fields and tags (like {@code id}).
+     * </ul>
      */
-    // TODO(b/33197203) (b/33269702): improve documentation: mention all cases, show examples, etc.
-    public static final int ASSIST_FLAG_SANITIZED_TEXT = 0x1;
+    // TODO(b/33197203) (b/34078930): improve documentation: mention all cases, show examples, etc.
+    // In particular, be more specific about webview restrictions
+    public static final int AUTO_FILL_FLAG_TYPE_FILL = 0x1;
 
     /**
-     * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should contain all
-     * type of data, even sensitive PII (Personally Identifiable Information) like passwords or
-     * credit card numbers.
+     * Set when the user explicitly asked a {@link android.service.autofill.AutoFillService} to save
+     * the value of the {@link View}s in an {@link android.app.Activity}.
+     *
+     * <p>The resulting {@link android.app.assist.AssistStructure} can contain any kind of PII
+     * (Personally Identifiable Information). For example, the text of password fields should be
+     * included since that's what's typically saved.
      */
-    public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 0x2;
+    public static final int AUTO_FILL_FLAG_TYPE_SAVE = 0x2;
 
     /**
      * Set to true when drawing cache is enabled and cannot be created.
@@ -6871,35 +6893,32 @@
      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
      * @param structure Fill in with structured view data.  The default implementation
      * fills in all data that can be inferred from the view itself.
-     *
-     * @deprecated As of API O sub-classes should override
-     * {@link #onProvideStructure(ViewStructure, int)} instead.
      */
-    // TODO(b/33197203): set proper API above
-    @Deprecated
     public void onProvideStructure(ViewStructure structure) {
-        onProvideStructure(structure, 0);
+        onProvideStructureForAssistOrAutoFill(structure, 0);
     }
 
     /**
-     * Called when assist structure is being retrieved from a view as part of
-     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
-     * of an auto-fill request.
-     *
-     * <p>The default implementation fills in all data that can be inferred from the view itself.
+     * Called when assist structure is being retrieved from a view as part of an auto-fill request.
      *
      * <p>The structure must be filled according to the request type, which is set in the
      * {@code flags} parameter - see the documentation on each flag for more details.
      *
-     * @param structure Fill in with structured view data. The default implementation
+     * @param structure Fill in with structured view data.  The default implementation
      * fills in all data that can be inferred from the view itself.
-     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
-     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
+     * @param flags optional flags (see {@link #AUTO_FILL_FLAG_TYPE_FILL} and
+     * {@link #AUTO_FILL_FLAG_TYPE_SAVE} for more info).
      */
-    public void onProvideStructure(ViewStructure structure, int flags) {
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        onProvideStructureForAssistOrAutoFill(structure, flags);
+    }
+
+    private void onProvideStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
+        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
+        // this method should take a boolean with the type of request.
         boolean forAutoFill = (flags
-                & (View.ASSIST_FLAG_SANITIZED_TEXT
-                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+                & (View.AUTO_FILL_FLAG_TYPE_FILL
+                        | View.AUTO_FILL_FLAG_TYPE_SAVE)) != 0;
         final int id = mID;
         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
                 && (id&0x0000ffff) != 0) {
@@ -6921,6 +6940,8 @@
             // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
             // reuse the accessibility id to save space.
             structure.setAutoFillId(getAccessibilityViewId());
+
+            structure.setAutoFillType(getAutoFillType());
         }
 
         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
@@ -6971,40 +6992,33 @@
      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
      * view's virtual accessibility nodes, if any.  You can override this for a more
      * optimal implementation providing this data.
-     *
-     * @deprecated As of API O, sub-classes should override
-     * {@link #onProvideVirtualStructure(ViewStructure, int)} instead.
      */
-    // TODO(b/33197203): set proper API above
-    @Deprecated
     public void onProvideVirtualStructure(ViewStructure structure) {
-        onProvideVirtualStructure(structure, 0);
+        onProvideVirtualStructureForAssistOrAutoFill(structure, 0);
     }
 
     /**
-     * Called when assist structure is being retrieved from a view as part of
-     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
-     * of an auto-fill request to generate additional virtual structure under this view.
+     * Called when assist structure is being retrieved from a view as part of an auto-fill request
+     * to generate additional virtual structure under this view.
      *
      * <p>The defaullt implementation uses {@link #getAccessibilityNodeProvider()} to try to
-     * generate this from the view's virtual accessibility nodes, if any.  You can override this
+     * generate this from the view's virtual accessibility nodes, if any. You can override this
      * for a more optimal implementation providing this data.
      *
      * <p>The structure must be filled according to the request type, which is set in the
      * {@code flags} parameter - see the documentation on each flag for more details.
      *
      * @param structure Fill in with structured view data.
-     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
-     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
+     * @param flags optional flags (see {@link #AUTO_FILL_FLAG_TYPE_FILL} and
+     * {@link #AUTO_FILL_FLAG_TYPE_SAVE} for more info).
      */
-    public void onProvideVirtualStructure(ViewStructure structure, int flags) {
-        boolean sanitize = (flags & View.ASSIST_FLAG_SANITIZED_TEXT) != 0;
+    public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
+        onProvideVirtualStructureForAssistOrAutoFill(structure, flags);
+    }
 
-        if (sanitize) {
-            // TODO(b/33197203): change populateVirtualStructure so it sanitizes data in this case.
-            return;
-        }
-
+    private void onProvideVirtualStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
+        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
+        // this method should take a boolean with the type of request.
         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
         if (provider != null) {
             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
@@ -7015,8 +7029,66 @@
         }
     }
 
+    /**
+     * Gets the {@link VirtualViewDelegate} responsible for auto-filling the virtual children of
+     * this view.
+     *
+     * <p>By default returns {@code null} but should be overridden when view provides a virtual
+     * hierachy on {@link OnProvideAssistDataListener} that takes flags used by the AutoFill
+     * Framework (such as {@link #AUTO_FILL_FLAG_TYPE_FILL} and
+     * {@link #AUTO_FILL_FLAG_TYPE_SAVE}).
+     */
+    @Nullable
+    public VirtualViewDelegate getAutoFillVirtualViewDelegate(
+            @SuppressWarnings("unused") VirtualViewDelegate.Callback callback) {
+        return null;
+    }
+
+    /**
+     * Automatically fills the content of this view with the {@code value}.
+     *
+     * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()} to
+     * support the AutoFill Framework.
+     *
+     * <p>Typically, it is implemented by:
+     *
+     * <ol>
+     * <li>Call the proper getter method on {@link AutoFillValue} to fetch the actual value.
+     * <li>Pass the actual value to the equivalent setter in the view.
+     * <ol>
+     *
+     * <p>For example, a text-field view would call:
+     *
+     * <pre class="prettyprint">
+     * CharSequence text = value.getTextValue();
+     * if (text != null) {
+     *     setText(text);
+     * }
+     * </pre>
+     */
+    public void autoFill(@SuppressWarnings("unused") AutoFillValue value) {
+    }
+
+    /**
+     * Describes the auto-fill type that should be used on callas to
+     * {@link #autoFill(AutoFillValue)} and
+     * {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
+     *
+     * <p>By default returns {@code null}, but views should override it (and
+     * {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
+     */
+    @Nullable
+    public AutoFillType getAutoFillType() {
+        return null;
+    }
+
     private void populateVirtualStructure(ViewStructure structure,
             AccessibilityNodeProvider provider, AccessibilityNodeInfo info, int flags) {
+        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
+        // this method should take a boolean with the type of request.
+
+        final boolean sanitized = (flags & View.AUTO_FILL_FLAG_TYPE_FILL) != 0;
+
         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
                 null, null, null);
         Rect rect = structure.getTempRect();
@@ -7054,7 +7126,10 @@
         CharSequence cname = info.getClassName();
         structure.setClassName(cname != null ? cname.toString() : null);
         structure.setContentDescription(info.getContentDescription());
-        if (info.getText() != null || info.getError() != null) {
+        if (!sanitized && (info.getText() != null || info.getError() != null)) {
+            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
+            // just set sanitized values (like text coming from resource files), rather than not
+            // setting it at all.
             structure.setText(info.getText(), info.getTextSelectionStart(),
                     info.getTextSelectionEnd());
         }
@@ -7075,14 +7150,9 @@
      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
      * implementation calls {@link #onProvideStructure} and
      * {@link #onProvideVirtualStructure}.
-     *
-     * @deprecated As of API O,  sub-classes should override
-     * {@link #dispatchProvideStructure(ViewStructure, int)} instead.
      */
-    // TODO(b/33197203): set proper API above
-    @Deprecated
     public void dispatchProvideStructure(ViewStructure structure) {
-        dispatchProvideStructure(structure, 0);
+        dispatchProvideStructureForAssistOrAutoFill(structure, 0);
     }
 
     /**
@@ -7091,22 +7161,33 @@
      * <p>The structure must be filled according to the request type, which is set in the
      * {@code flags} parameter - see the documentation on each flag for more details.
      *
-     * <p>The default implementation calls {@link #onProvideStructure(ViewStructure, int)} and
-     * {@link #onProvideVirtualStructure(ViewStructure, int)}.
+     * <p>The default implementation calls {@link #onProvideAutoFillStructure(ViewStructure, int)}
+     * and {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}.
      *
      * @param structure Fill in with structured view data.
-     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
-     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
+     * @param flags optional flags (see {@link #AUTO_FILL_FLAG_TYPE_FILL} and
+     * {@link #AUTO_FILL_FLAG_TYPE_SAVE} for more info).
      */
-    public void dispatchProvideStructure(ViewStructure structure, int flags) {
+    public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
+        dispatchProvideStructureForAssistOrAutoFill(structure, flags);
+    }
+
+    private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
+        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
+        // this method should take a boolean with the type of request.
         boolean forAutoFill = (flags
-                & (View.ASSIST_FLAG_SANITIZED_TEXT
-                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+                & (View.AUTO_FILL_FLAG_TYPE_FILL
+                        | View.AUTO_FILL_FLAG_TYPE_SAVE)) != 0;
 
         boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
         if (!blocked) {
-            onProvideStructure(structure, flags);
-            onProvideVirtualStructure(structure, flags);
+            if (forAutoFill) {
+                onProvideAutoFillStructure(structure, flags);
+                onProvideAutoFillVirtualStructure(structure, flags);
+            } else {
+                onProvideStructure(structure);
+                onProvideVirtualStructure(structure);
+            }
         } else {
             structure.setClassName(getAccessibilityClassName().toString());
             structure.setAssistBlocked(true);
@@ -14110,8 +14191,9 @@
      *            invalidated as well. This is usually true for a full
      *            invalidate, but may be set to false if the View's contents or
      *            dimensions have not changed.
+     * @hide
      */
-    void invalidate(boolean invalidateCache) {
+    public void invalidate(boolean invalidateCache) {
         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9ab368d..1f1af4b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3156,18 +3156,34 @@
     }
 
     /**
+     * Dispatch creation of {@link ViewStructure} down the hierarchy.  This implementation
+     * adds in all child views of the view group, in addition to calling the default View
+     * implementation.
+     */
+    @Override
+    public void dispatchProvideStructure(ViewStructure structure) {
+        super.dispatchProvideStructure(structure);
+        dispatchProvideStructureForAssistOrAutoFill(structure, 0);
+    }
+
+    /**
      * {@inheritDoc}
      *
      * <p>This implementation adds in all child views of the view group, in addition to calling the
      * default {@link View} implementation.
      */
     @Override
-    public void dispatchProvideStructure(ViewStructure structure, int flags) {
-        super.dispatchProvideStructure(structure, flags);
+    public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.dispatchProvideAutoFillStructure(structure, flags);
+        dispatchProvideStructureForAssistOrAutoFill(structure, flags);
+    }
 
+    private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
+        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
+        // this method should take a boolean with the type of request.
         boolean forAutoFill = (flags
-                & (View.ASSIST_FLAG_SANITIZED_TEXT
-                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
+                & (View.AUTO_FILL_FLAG_TYPE_FILL
+                        | View.AUTO_FILL_FLAG_TYPE_SAVE)) != 0;
 
         boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
 
@@ -3233,12 +3249,11 @@
                                 preorderedList, children, childIndex);
                         final ViewStructure cstructure = structure.newChild(i);
 
-                        // Must explicitly check which recursive method to call because child might
-                        // not be overriding the new, flags-based version
-                        if (flags == 0) {
-                            child.dispatchProvideStructure(cstructure);
+                        // Must explicitly check which recursive method to call.
+                        if (forAutoFill) {
+                            child.dispatchProvideAutoFillStructure(cstructure, flags);
                         } else {
-                            child.dispatchProvideStructure(cstructure, flags);
+                            child.dispatchProvideStructure(cstructure);
                         }
                     }
                     if (preorderedList != null) preorderedList.clear();
@@ -5340,11 +5355,96 @@
     }
 
     /**
+     * HW-only, Rect-ignoring invalidation path.
+     *
+     * Returns false if this path was unable to complete successfully. This means
+     * it hit a ViewParent it doesn't recognize and needs to fall back to calculating
+     * damage area.
+     *
+     * Hardware acceleration ignores damage rectangles, since native computes damage for everything
+     * drawn by HWUI (and SW layer / drawing cache doesn't keep track of damage area).
+     *
+     * Ignores opaque dirty optimizations, always using the full PFLAG_DIRTY flag.
+     *
+     * Ignores FLAG_OPTIMIZE_INVALIDATE, since we're not computing a rect,
+     *         so no point in optimizing that.
+     * @hide
+     */
+    public boolean tryInvalidateChildHardware(View child) {
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo == null || !attachInfo.mHardwareAccelerated) {
+            return false;
+        }
+
+        // verify it's ViewGroups up to a ViewRootImpl
+        ViewRootImpl viewRoot = null;
+        ViewParent parent = getParent();
+        while (parent != null) {
+            if (parent instanceof ViewGroup) {
+                parent = parent.getParent();
+            } else if (parent instanceof ViewRootImpl) {
+                viewRoot = (ViewRootImpl) parent;
+                break;
+            } else {
+                // unknown parent type, abort
+                return false;
+            }
+        }
+        if (viewRoot == null) {
+            // unable to find ViewRoot
+            return false;
+        }
+
+        final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0;
+
+        if (child.mLayerType != LAYER_TYPE_NONE) {
+            mPrivateFlags |= PFLAG_INVALIDATED;
+        }
+
+        parent = this;
+        do {
+            if (parent != viewRoot) {
+                // Note: we cast here without checking isinstance, to avoid cost of isinstance again
+                ViewGroup viewGroup = (ViewGroup) parent;
+                if (drawAnimation) {
+                    viewGroup.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
+                }
+
+                // We lazily use PFLAG_DIRTY, since computing opaque isn't worth the potential
+                // optimization in provides in a DisplayList world.
+                viewGroup.mPrivateFlags =
+                        (viewGroup.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DIRTY;
+
+                // simplified invalidateChildInParent behavior: clear cache validity to be safe,
+                // and mark inval if in layer
+                viewGroup.mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+                if (viewGroup.mLayerType != LAYER_TYPE_NONE) {
+                    viewGroup.mPrivateFlags |= PFLAG_INVALIDATED;
+                }
+            } else {
+                if (drawAnimation) {
+                    viewRoot.mIsAnimating = true;
+                }
+                ((ViewRootImpl) parent).invalidate();
+                return true;
+            }
+
+            parent = parent.getParent();
+        } while (parent != null);
+        return true;
+    }
+
+
+    /**
      * Don't call or override this method. It is used for the implementation of
      * the view hierarchy.
      */
     @Override
     public final void invalidateChild(View child, final Rect dirty) {
+        if (tryInvalidateChildHardware(child)) {
+            return;
+        }
+
         ViewParent parent = this;
 
         final AttachInfo attachInfo = mAttachInfo;
@@ -5352,8 +5452,7 @@
             // If the child is drawing an animation, we want to copy this flag onto
             // ourselves and the parent to make sure the invalidate request goes
             // through
-            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)
-                    == PFLAG_DRAW_ANIMATION;
+            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0;
 
             // Check whether the child that requests the invalidate is fully opaque
             // Views being animated or transformed are not considered opaque because we may
@@ -5454,10 +5553,10 @@
      */
     @Override
     public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
-        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
-                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
-            if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
-                        FLAG_OPTIMIZE_INVALIDATE) {
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID)) != 0) {
+            // either DRAWN, or DRAWING_CACHE_VALID
+            if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE))
+                    != FLAG_OPTIMIZE_INVALIDATE) {
                 dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
                         location[CHILD_TOP_INDEX] - mScrollY);
                 if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) {
@@ -5472,35 +5571,28 @@
                         dirty.setEmpty();
                     }
                 }
-                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
 
                 location[CHILD_LEFT_INDEX] = left;
                 location[CHILD_TOP_INDEX] = top;
-
-                if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= PFLAG_INVALIDATED;
-                }
-
-                return mParent;
-
             } else {
-                mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;
 
-                location[CHILD_LEFT_INDEX] = mLeft;
-                location[CHILD_TOP_INDEX] = mTop;
                 if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
                     dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
                 } else {
                     // in case the dirty rect extends outside the bounds of this container
                     dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
                 }
+                location[CHILD_LEFT_INDEX] = mLeft;
+                location[CHILD_TOP_INDEX] = mTop;
 
-                if (mLayerType != LAYER_TYPE_NONE) {
-                    mPrivateFlags |= PFLAG_INVALIDATED;
-                }
-
-                return mParent;
+                mPrivateFlags &= ~PFLAG_DRAWN;
             }
+            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
+            if (mLayerType != LAYER_TYPE_NONE) {
+                mPrivateFlags |= PFLAG_INVALIDATED;
+            }
+
+            return mParent;
         }
 
         return null;
@@ -5513,7 +5605,7 @@
      * damage area
      * @hide
      */
-    public boolean damageChildDeferred(View child) {
+    public boolean damageChildDeferred() {
         ViewParent parent = getParent();
         while (parent != null) {
             if (parent instanceof ViewGroup) {
@@ -5536,7 +5628,7 @@
      * @hide
      */
     public void damageChild(View child, final Rect dirty) {
-        if (damageChildDeferred(child)) {
+        if (damageChildDeferred()) {
             return;
         }
 
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index b770bd5..61cf0c7 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -283,8 +283,9 @@
             }
         }
 
+        /** @hide */
         @Override
-        void invalidate(boolean invalidateCache) {
+        public void invalidate(boolean invalidateCache) {
             super.invalidate(invalidateCache);
             if (mHostView != null) {
                 mHostView.invalidate(invalidateCache);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 68cd10c..b42f769 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -96,6 +96,7 @@
 import com.android.internal.policy.PhoneFallbackEventHandler;
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
+import com.android.internal.view.SurfaceCallbackHelper;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -240,7 +241,7 @@
     int mWidth;
     int mHeight;
     Rect mDirty;
-    boolean mIsAnimating;
+    public boolean mIsAnimating;
 
     private boolean mDragResizing;
     private boolean mInvalidateRootRequested;
@@ -261,7 +262,7 @@
     final Rect mTempRect; // used in the transaction to not thrash the heap.
     final Rect mVisRect; // used to retrieve visible rect of focused view.
 
-    boolean mTraversalScheduled;
+    public boolean mTraversalScheduled;
     int mTraversalBarrier;
     boolean mWillDrawSoon;
     /** Set to true while in performTraversals for detecting when die(true) is called from internal
@@ -528,11 +529,17 @@
      */
     public void notifyChildRebuilt() {
         if (mView instanceof RootViewSurfaceTaker) {
+            if (mSurfaceHolderCallback != null) {
+                mSurfaceHolder.removeCallback(mSurfaceHolderCallback);
+            }
+
             mSurfaceHolderCallback =
                 ((RootViewSurfaceTaker)mView).willYouTakeTheSurface();
+
             if (mSurfaceHolderCallback != null) {
                 mSurfaceHolder = new TakenSurfaceHolder();
                 mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
+                mSurfaceHolder.addCallback(mSurfaceHolderCallback);
             } else {
                 mSurfaceHolder = null;
             }
@@ -581,6 +588,7 @@
                     if (mSurfaceHolderCallback != null) {
                         mSurfaceHolder = new TakenSurfaceHolder();
                         mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
+                        mSurfaceHolder.addCallback(mSurfaceHolderCallback);
                     }
                 }
 
@@ -1957,7 +1965,6 @@
                         mSurfaceHolder.ungetCallbacks();
 
                         mIsCreating = true;
-                        mSurfaceHolderCallback.surfaceCreated(mSurfaceHolder);
                         SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
                         if (callbacks != null) {
                             for (SurfaceHolder.Callback c : callbacks) {
@@ -1967,8 +1974,6 @@
                         surfaceChanged = true;
                     }
                     if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) {
-                        mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
-                                lp.format, mWidth, mHeight);
                         SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
                         if (callbacks != null) {
                             for (SurfaceHolder.Callback c : callbacks) {
@@ -1981,7 +1986,6 @@
                 } else if (hadSurface) {
                     mSurfaceHolder.ungetCallbacks();
                     SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
-                    mSurfaceHolderCallback.surfaceDestroyed(mSurfaceHolder);
                     if (callbacks != null) {
                         for (SurfaceHolder.Callback c : callbacks) {
                             c.surfaceDestroyed(mSurfaceHolder);
@@ -2646,21 +2650,18 @@
             if (LOCAL_LOGV) {
                 Log.v(mTag, "FINISHED DRAWING: " + mWindowAttributes.getTitle());
             }
+
             if (mSurfaceHolder != null && mSurface.isValid()) {
-                mSurfaceHolderCallback.surfaceRedrawNeeded(mSurfaceHolder);
+                SurfaceCallbackHelper sch = new SurfaceCallbackHelper(mWindowSession, mWindow);
                 SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
-                if (callbacks != null) {
-                    for (SurfaceHolder.Callback c : callbacks) {
-                        if (c instanceof SurfaceHolder.Callback2) {
-                            ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(mSurfaceHolder);
-                        }
-                    }
+
+                sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
+            } else {
+                try {
+                    mWindowSession.finishDrawing(mWindow);
+                } catch (RemoteException e) {
                 }
             }
-            try {
-                mWindowSession.finishDrawing(mWindow);
-            } catch (RemoteException e) {
-            }
         }
     }
 
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index e9ff9d0..839e11c 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -19,6 +19,10 @@
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillValue;
+import android.view.autofill.VirtualViewDelegate;
 
 /**
  * Container for storing additional per-view data generated by {@link View#onProvideStructure
@@ -258,6 +262,12 @@
     public abstract ViewStructure newChild(int index);
 
     /**
+     * Like {@link #newChild(int)}, but providing a {@code virtualId} to the child so it can be
+     * auto-filled by {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
+     */
+    public abstract ViewStructure newChild(int index, int virtualId);
+
+    /**
      * Like {@link #newChild}, but allows the caller to asynchronously populate the returned
      * child.  It can transfer the returned {@link ViewStructure} to another thread for it
      * to build its content (and children etc).  Once done, some thread must call
@@ -268,6 +278,17 @@
     public abstract ViewStructure asyncNewChild(int index);
 
     /**
+     * Like {@link #asyncNewChild(int)}, but providing a {@code virtualId} to the child so it can be
+     * auto-filled by {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
+     */
+    public abstract ViewStructure asyncNewChild(int index, int virtualId);
+
+    /**
+     * Sets the {@link AutoFillType} that can be used to auto-fill this node.
+     */
+    public abstract void setAutoFillType(AutoFillType info);
+
+    /**
      * Call when done populating a {@link ViewStructure} returned by
      * {@link #asyncNewChild}.
      */
@@ -277,5 +298,8 @@
     public abstract Rect getTempRect();
 
     /** @hide */
-    public abstract void setAutoFillId(int autoFillId);
+    public abstract void setAutoFillId(int viewId);
+
+    /** @hide */
+    public abstract AutoFillId getAutoFillId();
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index caa09cc..dd85256 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -437,6 +437,15 @@
     }
 
     /**
+     * Holds the contents of a starting window. {@link #addSplashScreen} needs to wrap the
+     * contents of the starting window into an class implementing this interface, which then will be
+     * held by WM and passed into {@link #removeSplashScreen} when the starting window is no
+     * longer needed.
+     */
+    interface StartingSurface {
+    }
+
+    /**
      * Interface for calling back in to the window manager that is private
      * between it and the policy.
      */
@@ -738,17 +747,17 @@
      *        context to for resources.
      *
      * @return Optionally you can return the View that was used to create the
-     *         window, for easy removal in removeStartingWindow.
+     *         window, for easy removal in removeSplashScreen.
      *
-     * @see #removeStartingWindow
+     * @see #removeSplashScreen
      */
-    public View addStartingWindow(IBinder appToken, String packageName,
-            int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel,
-            int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig);
+    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
+            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
+            int logo, int windowFlags, Configuration overrideConfig);
 
     /**
      * Called when the first window of an application has been displayed, while
-     * {@link #addStartingWindow} has created a temporary initial window for
+     * {@link #addSplashScreen} has created a temporary initial window for
      * that application.  You should at this point remove the window from the
      * window manager.  This is called without the window manager locked so
      * that you can call back into it.
@@ -759,11 +768,11 @@
      * even if you previously returned one.
      *
      * @param appToken Token of the application that has started.
-     * @param window Window View that was returned by createStartingWindow.
+     * @param surface Surface that was returned by {@link #addSplashScreen}.
      *
-     * @see #addStartingWindow
+     * @see #addSplashScreen
      */
-    public void removeStartingWindow(IBinder appToken, View window);
+    public void removeSplashScreen(IBinder appToken, StartingSurface surface);
 
     /**
      * Prepare for a window being added to the window manager.  You can throw an
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 9127861..91468da 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -25,7 +25,13 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.InputType;
+import android.text.Spannable;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.style.AccessibilityClickableSpan;
+import android.text.style.AccessibilityURLSpan;
+import android.text.style.ClickableSpan;
+import android.text.style.URLSpan;
 import android.util.ArraySet;
 import android.util.LongArray;
 import android.util.Pools.SynchronizedPool;
@@ -464,6 +470,14 @@
     public static final String ACTION_ARGUMENT_PROGRESS_VALUE =
             "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
 
+    /**
+     * Argument to pass the {@link AccessibilityClickableSpan}.
+     * For use with R.id.accessibilityActionClickOnClickableSpan
+     * @hide
+     */
+    public static final String ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN =
+            "android.view.accessibility.action.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN";
+
     // Focus types
 
     /**
@@ -628,6 +642,8 @@
 
     private CharSequence mPackageName;
     private CharSequence mClassName;
+    // Hidden, unparceled value used to hold the original value passed to setText
+    private CharSequence mOriginalText;
     private CharSequence mText;
     private CharSequence mError;
     private CharSequence mContentDescription;
@@ -2213,14 +2229,49 @@
 
     /**
      * Gets the text of this node.
+     * <p>
+     *   <strong>Note:</strong> If the text contains {@link ClickableSpan}s or {@link URLSpan}s,
+     *   these spans will have been replaced with ones whose {@link ClickableSpan#onClick(View)}
+     *   can be called from an {@link AccessibilityService}. When called from a service, the
+     *   {@link View} argument is ignored and the corresponding span will be found on the view that
+     *   this {@code AccessibilityNodeInfo} represents and called with that view as its argument.
+     *   <p>
+     *   This treatment of {@link ClickableSpan}s means that the text returned from this method may
+     *   different slightly one passed to {@link #setText(CharSequence)}, although they will be
+     *   equivalent according to {@link TextUtils#equals(CharSequence, CharSequence)}. The
+     *   {@link ClickableSpan#onClick(View)} of any spans, however, will generally not work outside
+     *   of an accessibility service.
+     * </p>
      *
      * @return The text.
      */
     public CharSequence getText() {
+        // Attach this node to any spans that need it
+        if (mText instanceof Spanned) {
+            Spanned spanned = (Spanned) mText;
+            AccessibilityClickableSpan[] clickableSpans =
+                    spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class);
+            for (int i = 0; i < clickableSpans.length; i++) {
+                clickableSpans[i].setAccessibilityNodeInfo(this);
+            }
+            AccessibilityURLSpan[] urlSpans =
+                    spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class);
+            for (int i = 0; i < urlSpans.length; i++) {
+                urlSpans[i].setAccessibilityNodeInfo(this);
+            }
+        }
         return mText;
     }
 
     /**
+     * Get the text passed to setText before any changes to the spans.
+     * @hide
+     */
+    public CharSequence getOriginalText() {
+        return mOriginalText;
+    }
+
+    /**
      * Sets the text of this node.
      * <p>
      *   <strong>Note:</strong> Cannot be called from an
@@ -2234,6 +2285,34 @@
      */
     public void setText(CharSequence text) {
         enforceNotSealed();
+        mOriginalText = text;
+        // Replace any ClickableSpans in mText with placeholders
+        if (text instanceof Spanned) {
+            ClickableSpan[] spans =
+                    ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
+            if (spans.length > 0) {
+                Spannable spannable = Spannable.Factory.getInstance().newSpannable(text);
+                for (int i = 0; i < spans.length; i++) {
+                    ClickableSpan span = spans[i];
+                    if ((span instanceof AccessibilityClickableSpan)
+                            || (span instanceof AccessibilityURLSpan)) {
+                        // We've already done enough
+                        break;
+                    }
+                    int spanToReplaceStart = spannable.getSpanStart(span);
+                    int spanToReplaceEnd = spannable.getSpanEnd(span);
+                    int spanToReplaceFlags = spannable.getSpanFlags(span);
+                    spannable.removeSpan(span);
+                    ClickableSpan replacementSpan = (span instanceof URLSpan)
+                            ? new AccessibilityURLSpan((URLSpan) span)
+                            : new AccessibilityClickableSpan(span.getId());
+                    spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
+                            spanToReplaceFlags);
+                }
+                mText = spannable;
+                return;
+            }
+        }
         mText = (text == null) ? null : text.subSequence(0, text.length());
     }
 
diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java
index 09d4dfc..767024e 100644
--- a/core/java/android/view/animation/AnimationSet.java
+++ b/core/java/android/view/animation/AnimationSet.java
@@ -237,7 +237,7 @@
                 mDuration = a.getStartOffset() + a.getDuration();
                 mLastEnd = mStartOffset + mDuration;
             } else {
-                mLastEnd = Math.max(mLastEnd, a.getStartOffset() + a.getDuration());
+                mLastEnd = Math.max(mLastEnd, mStartOffset + a.getStartOffset() + a.getDuration());
                 mDuration = mLastEnd - mStartOffset;
             }
         }
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/view/autofill/AutoFillId.aidl
similarity index 63%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/view/autofill/AutoFillId.aidl
index d6d4f39..56f0338 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/view/autofill/AutoFillId.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * 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
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
+package android.view.autofill;
 
-import java.util.List;
-
-/**
- * @hide
- */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
-}
+parcelable AutoFillId;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillId.java b/core/java/android/view/autofill/AutoFillId.java
new file mode 100644
index 0000000..b7b694d
--- /dev/null
+++ b/core/java/android/view/autofill/AutoFillId.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A unique identifier for an auto-fill node inside an {@link android.app.Activity}.
+ */
+public final class AutoFillId implements Parcelable {
+
+    private int mViewId;
+    private boolean mVirtual;
+    private int mVirtualId;
+
+    /** @hide */
+    public AutoFillId(int id) {
+        mVirtual = false;
+        mViewId = id;
+    }
+
+    /** @hide */
+    public AutoFillId(AutoFillId parent, int virtualChildId) {
+        mVirtual = true;
+        mViewId = parent.mViewId;
+        mVirtualId = virtualChildId;
+    }
+
+    /** @hide */
+    public int getViewId() {
+        return mViewId;
+    }
+
+    /** @hide */
+    public int getVirtualChildId() {
+        return mVirtualId;
+    }
+
+    /** @hide */
+    public boolean isVirtual() {
+        return mVirtual;
+    }
+
+    /////////////////////////////////
+    //  Object "contract" methods. //
+    /////////////////////////////////
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + mViewId;
+        result = prime * result + mVirtualId;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        final AutoFillId other = (AutoFillId) obj;
+        if (mViewId != other.mViewId) return false;
+        if (mVirtualId != other.mVirtualId) return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        final StringBuilder builder = new StringBuilder("FieldId [viewId=").append(mViewId);
+        if (mVirtual) {
+            builder.append(", virtualId=").append(mVirtualId);
+        }
+        return builder.append(']').toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mViewId);
+        parcel.writeInt(mVirtual ? 1 : 0);
+        parcel.writeInt(mVirtualId);
+    }
+
+    private AutoFillId(Parcel parcel) {
+        mViewId = parcel.readInt();
+        mVirtual = parcel.readInt() == 1;
+        mVirtualId = parcel.readInt();
+    }
+
+    public static final Parcelable.Creator<AutoFillId> CREATOR =
+            new Parcelable.Creator<AutoFillId>() {
+        @Override
+        public AutoFillId createFromParcel(Parcel source) {
+            return new AutoFillId(source);
+        }
+
+        @Override
+        public AutoFillId[] newArray(int size) {
+            return new AutoFillId[size];
+        }
+    };
+}
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/view/autofill/AutoFillType.aidl
similarity index 63%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/view/autofill/AutoFillType.aidl
index d6d4f39..a63d7c5 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/view/autofill/AutoFillType.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
+package android.view.autofill;
 
-import java.util.List;
-
-/**
- * @hide
- */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
-}
+parcelable AutoFillType;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillType.java b/core/java/android/view/autofill/AutoFillType.java
new file mode 100644
index 0000000..017f7f8
--- /dev/null
+++ b/core/java/android/view/autofill/AutoFillType.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Defines the type of a object that can be used to auto-fill a {@link View} so the
+ * {@link android.service.autofill.AutoFillService} can use the proper {@link AutoFillValue} to
+ * fill it.
+ *
+ * <p>Some {@link AutoFillType}s can have an optional {@code sub-type}: the
+ * main {@code type} defines the view's UI control category (like a text field), while the optional
+ * {@code sub-type} define its semantics (like a postal address).
+ */
+public final class AutoFillType implements Parcelable {
+
+    // Cached instance for types that don't have subtype; it uses the "lazy initialization holder
+    // class idiom" (Effective Java, Item 71) to avoid memory utilization when auto-fill is not
+    // enabled.
+    private static class DefaultTypesHolder {
+        static final AutoFillType TOGGLE = new AutoFillType(TYPE_TOGGLE, 0);
+        static final AutoFillType LIST = new AutoFillType(TYPE_LIST, 0);
+    }
+
+    private static final int TYPE_TEXT = 1;
+    private static final int TYPE_TOGGLE = 2;
+    // TODO(b/33197203): make sure it works with Spinners and/or add a new type for them
+    // (since they're often used for credit card selection)
+    private static final int TYPE_LIST = 3;
+
+    // TODO(b/33197203): add others, like date picker? That would be trick, because they're set as:
+    // updateDate(int year, int month, int dayOfMonth)
+    // So, we would have to either use a long representing the Date.time(), or a custom long
+    // representing:
+    // year * 10000 + month * 100 + day
+    // Then a custom getDatePickerValue(Bundle) that returns an immutable object with these 3 fields
+
+    private final int mType;
+    private final int mSubType;
+
+    private AutoFillType(int type, int subType) {
+        mType = type;
+        mSubType = subType;
+    }
+
+    /**
+     * Checks if this is a type for a text field, which is filled by a {@link CharSequence}.
+     *
+     * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+     * {@link AutoFillValue#forText(CharSequence)}, and the value of a bundle passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getTextValue()}.
+     *
+     * <p>Sub-type for this type is the value defined by {@link TextView#getInputType()}.
+     */
+    public boolean isText() {
+        return mType == TYPE_TEXT;
+    }
+
+    /**
+     * Checks if this is a a type for a togglable field, which is filled by a {@code boolean}.
+     *
+     * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+     * {@link AutoFillValue#forToggle(boolean)}, and the value of a bundle passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getToggleValue()}.
+     *
+     * <p>This type has no sub-types.
+     */
+    public boolean isToggle() {
+        return mType == TYPE_TOGGLE;
+    }
+
+    /**
+     * Checks if this is a type for a selection list field, which is filled by a {@code integer}
+     * representing the element index inside the list (starting at {@code 0}.
+     *
+     * <p>{@link AutoFillValue} instances for auto-filling a {@link View} can be obtained through
+     * {@link AutoFillValue#forList(int)}, and the value of a bundle passed to auto-fill a
+     * {@link View} can be fetched through {@link AutoFillValue#getListValue()}.
+     *
+     * <p>This type has no sub-types.
+     */
+    public boolean isList() {
+        return mType == TYPE_LIST;
+    }
+
+
+    /**
+     * Gets the optional sub-type, representing the {@link View}'s semantic.
+     *
+     * @return {@code 0} if type does not support sub-types.
+     */
+    public int getSubType() {
+        return mSubType;
+    }
+
+    /////////////////////////////////////
+    //  Object "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        return "AutoFillType [type=" + mType + ", subType=" + mSubType + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + mSubType;
+        result = prime * result + mType;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        final AutoFillType other = (AutoFillType) obj;
+        if (mSubType != other.mSubType) return false;
+        if (mType != other.mType) return false;
+        return true;
+    }
+
+    /////////////////////////////////////
+    //  Parcelable "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mType);
+        parcel.writeInt(mSubType);
+    }
+
+    private AutoFillType(Parcel parcel) {
+        mType = parcel.readInt();
+        mSubType = parcel.readInt();
+    }
+
+    public static final Parcelable.Creator<AutoFillType> CREATOR =
+            new Parcelable.Creator<AutoFillType>() {
+        @Override
+        public AutoFillType createFromParcel(Parcel source) {
+            return new AutoFillType(source);
+        }
+
+        @Override
+        public AutoFillType[] newArray(int size) {
+            return new AutoFillType[size];
+        }
+    };
+
+    ////////////////////
+    // Factory methods //
+    ////////////////////
+
+    /**
+     * Creates a text field type, which is filled by a {@link CharSequence}.
+     *
+     * <p>See {@link #isText()} for more info.
+     */
+    public static AutoFillType forText(int inputType) {
+        return new AutoFillType(TYPE_TEXT, inputType);
+    }
+
+    /**
+     * Creates a type that can be toggled which is filled by a {@code boolean}.
+     *
+     * <p>See {@link #isToggle()} for more info.
+     */
+    public static AutoFillType forToggle() {
+        return DefaultTypesHolder.TOGGLE;
+    }
+
+    /**
+     * Creates a selection list, which is filled by a {@code integer} representing the element index
+     * inside the list (starting at {@code 0}.
+     *
+     * <p>See {@link #isList()} for more info.
+     */
+    public static AutoFillType forList() {
+        return DefaultTypesHolder.LIST;
+    }
+}
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/view/autofill/AutoFillValue.aidl
similarity index 63%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/view/autofill/AutoFillValue.aidl
index d6d4f39..3b284b9 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/view/autofill/AutoFillValue.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
+package android.view.autofill;
 
-import java.util.List;
-
-/**
- * @hide
- */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
-}
+parcelable AutoFillValue;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
new file mode 100644
index 0000000..c39f26b
--- /dev/null
+++ b/core/java/android/view/autofill/AutoFillValue.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+
+/**
+ * Abstracts how a {@link View} can be auto-filled by an
+ * {@link android.service.autofill.AutoFillService}.
+ *
+ * <p>Each {@link AutoFillValue} has a {@code type} and optionally a {@code sub-type}: the
+ * {@code type} defines the view's UI control category (like a text field), while the optional
+ * {@code sub-type} define its semantics (like a postal address).
+ */
+public final class AutoFillValue implements Parcelable {
+
+    private final CharSequence mText;
+    private final int mListIndex;
+    private final boolean mToggle;
+
+    private AutoFillValue(CharSequence text, int listIndex, boolean toggle) {
+        mText = text;
+        mListIndex = listIndex;
+        mToggle = toggle;
+    }
+
+    /**
+     * Gets the value to auto-fill a text field.
+     *
+     * <p>See {@link AutoFillType#isText()} for more info.
+     */
+    public CharSequence getTextValue() {
+        return mText;
+    }
+
+    /**
+     * Gets the value to auto-fill a toggable field.
+     *
+     * <p>See {@link AutoFillType#isToggle()} for more info.
+     */
+    public boolean getToggleValue() {
+        return mToggle;
+    }
+
+    /**
+     * Gets the value to auto-fill a selection list field.
+     *
+     * <p>See {@link AutoFillType#isList()} for more info.
+     */
+    public int getListValue() {
+        return mListIndex;
+    }
+
+    /////////////////////////////////////
+    //  Object "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        return "AutoFillValue[text=" + mText + ", listIndex=" + mListIndex + ", toggle=" + mToggle
+                + "]";
+    }
+
+    /////////////////////////////////////
+    //  Parcelable "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeCharSequence(mText);
+        parcel.writeInt(mListIndex);
+        parcel.writeInt(mToggle ? 1 : 0);
+    }
+
+    private AutoFillValue(Parcel parcel) {
+        mText = parcel.readCharSequence();
+        mListIndex = parcel.readInt();
+        mToggle = parcel.readInt() == 1;
+    }
+
+    public static final Parcelable.Creator<AutoFillValue> CREATOR =
+            new Parcelable.Creator<AutoFillValue>() {
+        @Override
+        public AutoFillValue createFromParcel(Parcel source) {
+            return new AutoFillValue(source);
+        }
+
+        @Override
+        public AutoFillValue[] newArray(int size) {
+            return new AutoFillValue[size];
+        }
+    };
+
+    ////////////////////
+    // Factory methods //
+    ////////////////////
+
+    // TODO(b/33197203): add unit tests for each supported type (new / get should return same value)
+    /**
+     * Creates a new {@link AutoFillValue} to auto-fill a text field.
+     *
+     * <p>See {@link AutoFillType#isText()} for more info.
+     */
+    public static AutoFillValue forText(CharSequence value) {
+        return new AutoFillValue(value, 0, false);
+    }
+
+    /**
+     * Creates a new {@link AutoFillValue} to auto-fill a toggable field.
+     *
+     * <p>See {@link AutoFillType#isToggle()} for more info.
+     */
+    public static AutoFillValue forToggle(boolean value) {
+        return new AutoFillValue(null, 0, value);
+    }
+
+    /**
+     * Creates a new {@link AutoFillValue} to auto-fill a selection list field.
+     *
+     * <p>See {@link AutoFillType#isList()} for more info.
+     */
+    public static AutoFillValue forList(int value) {
+        return new AutoFillValue(null, value, false);
+    }
+}
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/view/autofill/Dataset.aidl
similarity index 63%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/view/autofill/Dataset.aidl
index d6d4f39..2a8e67c 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/view/autofill/Dataset.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
+package android.view.autofill;
 
-import java.util.List;
-
-/**
- * @hide
- */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
-}
+parcelable Dataset;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/Dataset.java b/core/java/android/view/autofill/Dataset.java
new file mode 100644
index 0000000..a73eb774
--- /dev/null
+++ b/core/java/android/view/autofill/Dataset.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+import static android.view.autofill.Helper.append;
+
+import android.app.Activity;
+import android.app.assist.AssistStructure.ViewNode;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.autofill.AutoFillService;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A set of data that can be used to auto-fill an {@link Activity}.
+ *
+ * <p>It contains:
+ *
+ * <ol>
+ *   <li>A name used to identify the dataset in the UI.
+ *   <li>A list of id/value pairs for the fields that can be auto-filled.
+ *   <li>An optional {@link Bundle} with extras (used only by the service creating it).
+ * </ol>
+ *
+ * See {@link FillResponse} for examples.
+ */
+public final class Dataset implements Parcelable {
+
+    private final CharSequence mName;
+    private final ArrayList<DatasetField> mFields;
+    private final Bundle mExtras;
+
+    private Dataset(Dataset.Builder builder) {
+        mName = builder.mName;
+        // TODO(b/33197203): make an immutable copy of mFields?
+        mFields = builder.mFields;
+        mExtras = builder.mExtras;
+    }
+
+    /** @hide */
+    public CharSequence getName() {
+        return mName;
+    }
+
+    /** @hide */
+    public List<DatasetField> getFields() {
+        return mFields;
+    }
+
+    /** @hide */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        final StringBuilder builder = new StringBuilder("Dataset [name=").append(mName)
+                .append(", fields=").append(mFields).append(", extras=");
+        append(builder, mExtras);
+        return builder.append(']').toString();
+    }
+
+    /**
+     * A builder for {@link Dataset} objects.
+     */
+    public static final class Builder {
+        private CharSequence mName;
+        private final ArrayList<DatasetField> mFields = new ArrayList<>();
+        private Bundle mExtras;
+
+        /**
+         * Creates a new builder.
+         *
+         * @param name Name used to identify the dataset in the UI. Typically it's the same value as
+         * the first field in the dataset (like username or email address) or an user-provided name
+         * (like "My Work Address").
+         */
+        public Builder(CharSequence name) {
+            mName = Preconditions.checkStringNotEmpty(name, "name cannot be empty or null");
+        }
+
+        /**
+         * Sets the value of a field.
+         *
+         * @param id id returned by {@link ViewNode#getAutoFillId()}.
+         * @param value value to be auto filled.
+         */
+        public Dataset.Builder setValue(AutoFillId id, AutoFillValue value) {
+            putField(new DatasetField(id, value));
+            return this;
+        }
+
+        /**
+         * Creates a new {@link Dataset} instance.
+         */
+        public Dataset build() {
+            return new Dataset(this);
+        }
+
+        /**
+         * Sets a {@link Bundle} that will be passed to subsequent calls to {@link AutoFillService}
+         * methods such as
+         * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+         * android.os.CancellationSignal, android.service.autofill.SaveCallback)}, using
+         * {@link AutoFillService#EXTRA_DATASET_EXTRAS} as the key.
+         *
+         * <p>It can be used to keep service state in between calls.
+         */
+        public Builder setExtras(Bundle extras) {
+            mExtras = Objects.requireNonNull(extras, "extras cannot be null");
+            return this;
+        }
+
+        /**
+         * Emulates {@code Map.put()} by adding a new field to the list if its id is not the yet,
+         * or replacing the existing one.
+         */
+        private void putField(DatasetField field) {
+            // TODO(b/33197203): check if already exists and replaces it if so
+            mFields.add(field);
+        }
+    }
+
+    /////////////////////////////////////
+    //  Parcelable "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeCharSequence(mName);
+        parcel.writeList(mFields);
+        parcel.writeBundle(mExtras);
+    }
+
+    @SuppressWarnings("unchecked")
+    private Dataset(Parcel parcel) {
+        mName = parcel.readCharSequence();
+        mFields = parcel.readArrayList(null);
+        mExtras = parcel.readBundle();
+    }
+
+    public static final Parcelable.Creator<Dataset> CREATOR = new Parcelable.Creator<Dataset>() {
+        @Override
+        public Dataset createFromParcel(Parcel source) {
+            return new Dataset(source);
+        }
+
+        @Override
+        public Dataset[] newArray(int size) {
+            return new Dataset[size];
+        }
+    };
+}
diff --git a/core/java/android/view/autofill/DatasetField.java b/core/java/android/view/autofill/DatasetField.java
new file mode 100644
index 0000000..c6b92ac
--- /dev/null
+++ b/core/java/android/view/autofill/DatasetField.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public final class DatasetField implements Parcelable {
+
+    private final AutoFillId mId;
+    private final AutoFillValue mValue;
+
+    DatasetField(AutoFillId id, AutoFillValue value) {
+        mId = id;
+        mValue = value;
+    }
+
+    public AutoFillId getId() {
+        return mId;
+    }
+
+    public AutoFillValue getValue() {
+        return mValue;
+    }
+
+    /////////////////////////////////
+    //  Object "contract" methods. //
+    /////////////////////////////////
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        return "DatasetField [id=" + mId + ", value=" + mValue + "]";
+    }
+
+    /////////////////////////////////////
+    //  Parcelable "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeParcelable(mId, 0);
+        parcel.writeParcelable(mValue, 0);
+    }
+
+    private DatasetField(Parcel parcel) {
+        mId = parcel.readParcelable(null);
+        mValue = parcel.readParcelable(null);
+    }
+
+    public static final Parcelable.Creator<DatasetField> CREATOR =
+            new Parcelable.Creator<DatasetField>() {
+        @Override
+        public DatasetField createFromParcel(Parcel source) {
+            return new DatasetField(source);
+        }
+
+        @Override
+        public DatasetField[] newArray(int size) {
+            return new DatasetField[size];
+        }
+    };
+}
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/view/autofill/FieldId.aidl
similarity index 63%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/view/autofill/FieldId.aidl
index d6d4f39..35af645 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/view/autofill/FieldId.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
+package android.view.autofill;
 
-import java.util.List;
-
-/**
- * @hide
- */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
-}
+parcelable FieldId;
\ No newline at end of file
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/view/autofill/FillResponse.aidl
similarity index 63%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to core/java/android/view/autofill/FillResponse.aidl
index d6d4f39..b018f15 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/view/autofill/FillResponse.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
+/**
+ * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
+package android.view.autofill;
 
-import java.util.List;
-
-/**
- * @hide
- */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
-}
+parcelable FillResponse;
\ No newline at end of file
diff --git a/core/java/android/view/autofill/FillResponse.java b/core/java/android/view/autofill/FillResponse.java
new file mode 100644
index 0000000..3a14767
--- /dev/null
+++ b/core/java/android/view/autofill/FillResponse.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+import static android.view.autofill.Helper.append;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.autofill.AutoFillService;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Response for a
+ * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
+ * android.os.CancellationSignal, android.service.autofill.FillCallback)}
+ * request.
+ *
+ * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
+ * fields that can be auto-filled together. For example, for a login page with username/password
+ * where the user only have one account in the service, the response could be:
+ *
+ * <pre class="prettyprint">
+ *  new FillResponse.Builder()
+ *      .add(new Dataset.Builder("homer")
+ *          .setTextFieldValue(id1, "homer")
+ *          .setTextFieldValue(id2, "D'OH!")
+ *          .build())
+ *      .build();
+ * </pre>
+ *
+ * <p>If the user had 2 accounts, each with its own user-provided names, the response could be:
+ *
+ * <pre class="prettyprint">
+ *  new FillResponse.Builder()
+ *      .add(new Dataset.Builder("Homer's Account")
+ *          .setTextFieldValue(id1, "homer")
+ *          .setTextFieldValue(id2, "D'OH!")
+ *          .build())
+ *      .add(new Dataset.Builder("Bart's Account")
+ *          .setTextFieldValue(id1, "elbarto")
+ *          .setTextFieldValue(id2, "cowabonga")
+ *          .build())
+ *      .build();
+ * </pre>
+ *
+ * <p>If the user does not have any data associated with this {@link Activity} but the service
+ * wants to offer the user the option to save the data that was entered, then the service could
+ * populate the response with {@code savableIds} instead of {@link Dataset}s:
+ *
+ * <pre class="prettyprint">
+ *  new FillResponse.Builder()
+ *      .addSavableFields(id1, id2)
+ *      .build();
+ * </pre>
+ *
+ * <p>Similarly, there might be cases where the user data on the service is enough to populate some
+ * fields but not all, and the service would still be interested on saving the other fields. In this
+ * scenario, the service could populate the response with both {@link Dataset}s and
+ * {@code savableIds}:
+ *
+ * <pre class="prettyprint">
+ *   new FillResponse.Builder()
+ *       .add(new Dataset.Builder("Homer")
+ *          .setTextFieldValue(id1, "Homer")                  // first name
+ *          .setTextFieldValue(id2, "Simpson")                // last name
+ *          .setTextFieldValue(id3, "742 Evergreen Terrace")  // street
+ *          .setTextFieldValue(id4, "Springfield")            // city
+ *          .build())
+ *       .addSavableFields(id5, id6) // state and zipcode
+ *       .build();
+ *
+ * </pre>
+ *
+ * <p>Notice that the ids that are part of a dataset (ids 1 to 4, in this example) are automatically
+ * added to the {@code savableIds} list.
+ *
+ * <p>If the service has multiple {@link Dataset}s with multiple options for some fields on each
+ * dataset (for example, multiple accounts with both a home and work address), then it should
+ * "partition" the {@link Activity} in sections and populate the response with just a subset of the
+ * data that would fulfill the first section; then once the user fills the first section and taps
+ * a field from the next section, the Android system would issue another request for that section,
+ * and so on. For example, the first response could be:
+ *
+ * <pre class="prettyprint">
+ *  new FillResponse.Builder()
+ *      .add(new Dataset.Builder("Homer")
+ *          .setTextFieldValue(id1, "Homer")
+ *          .setTextFieldValue(id2, "Simpson")
+ *          .build())
+ *      .add(new Dataset.Builder("Bart")
+ *          .setTextFieldValue(id1, "Bart")
+ *          .setTextFieldValue(id2, "Simpson")
+ *          .build())
+ *      .build();
+ * </pre>
+ *
+ * <p>Then after the user picks the {@code Homer} dataset and taps the {@code Street} field to
+ * trigger another auto-fill request, the second response could be:
+ *
+ * <pre class="prettyprint">
+ *  new FillResponse.Builder()
+ *      .add(new Dataset.Builder("Home")
+ *          .setTextFieldValue(id3, "742 Evergreen Terrace")
+ *          .setTextFieldValue(id4, "Springfield")
+ *          .build())
+ *      .add(new Dataset.Builder("Work")
+ *          .setTextFieldValue(id3, "Springfield Nuclear Power Plant")
+ *          .setTextFieldValue(id4, "Springfield")
+ *          .build())
+ *      .build();
+ * </pre>
+ *
+ * <p>Finally, the service can use the {@link FillResponse.Builder#setExtras(Bundle)} and/or
+ * {@link Dataset.Builder#setExtras(Bundle)} methods to pass
+ * a {@link Bundle} with service-specific data use to identify this response on future calls (like
+ * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+ * android.os.CancellationSignal, android.service.autofill.SaveCallback)}) - such bundle will be
+ * available as the {@link AutoFillService#EXTRA_RESPONSE_EXTRAS} extra in
+ * that method's {@code extras} argument.
+ */
+public final class FillResponse implements Parcelable {
+
+    private final List<Dataset> mDatasets;
+    private final AutoFillId[] mSavableIds;
+    private final Bundle mExtras;
+
+    private FillResponse(Builder builder) {
+        // TODO(b/33197203): make it immutable?
+        mDatasets = builder.mDatasets;
+        final int size = builder.mSavableIds.size();
+        mSavableIds = new AutoFillId[size];
+        int i = 0;
+        for (AutoFillId id : builder.mSavableIds) {
+            mSavableIds[i++] = id;
+        }
+        mExtras = builder.mExtras;
+    }
+
+    /** @hide */
+    public List<Dataset> getDatasets() {
+        return mDatasets;
+    }
+
+    /** @hide */
+    public AutoFillId[] getSavableIds() {
+        return mSavableIds;
+    }
+
+    /** @hide */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /**
+     * Builder for {@link FillResponse} objects.
+     */
+    public static final class Builder {
+        private final List<Dataset> mDatasets = new ArrayList<>();
+        private final Set<AutoFillId> mSavableIds = new HashSet<>();
+        private  Bundle mExtras;
+
+        /**
+         * Adds a new {@link Dataset} to this response.
+         *
+         * @throws IllegalArgumentException if a dataset with same {@code name} already exists.
+         */
+        public Builder addDataset(Dataset dataset) {
+            Preconditions.checkNotNull(dataset, "dataset cannot be null");
+            // TODO(b/33197203): check if name already exists
+            // TODO(b/33197203): check if authId already exists (and update javadoc)
+            mDatasets.add(dataset);
+            for (DatasetField field : dataset.getFields()) {
+                mSavableIds.add(field.getId());
+            }
+            return this;
+        }
+
+        /**
+         * Adds ids of additional fields that the service would be interested to save (through
+         * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+         * android.os.CancellationSignal, android.service.autofill.SaveCallback)}) but were not
+         * indirectly set through {@link #addDataset(Dataset)}.
+         *
+         * <p>See {@link FillResponse} for examples.
+         */
+        public Builder addSavableFields(AutoFillId...ids) {
+            for (AutoFillId id : ids) {
+                mSavableIds.add(id);
+            }
+            return this;
+        }
+
+        /**
+         * Sets a {@link Bundle} that will be passed to subsequent calls to {@link AutoFillService}
+         * methods such as
+         * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+         * android.os.CancellationSignal, android.service.autofill.SaveCallback)}, using
+         * {@link AutoFillService#EXTRA_RESPONSE_EXTRAS} as the key.
+         *
+         * <p>It can be used when to keep service state in between calls.
+         */
+        public Builder setExtras(Bundle extras) {
+            mExtras = Objects.requireNonNull(extras, "extras cannot be null");
+            return this;
+        }
+
+        /**
+         * Builds a new {@link FillResponse} instance.
+         */
+        public FillResponse build() {
+            return new FillResponse(this);
+        }
+    }
+
+    /////////////////////////////////////
+    //  Object "contract" methods. //
+    /////////////////////////////////////
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        final StringBuilder builder = new StringBuilder("FillResponse: [datasets=")
+                .append(mDatasets).append(", savableIds=").append(Arrays.toString(mSavableIds))
+                .append(", extras=");
+        append(builder, mExtras);
+        return builder.append(']').toString();
+    }
+
+    /////////////////////////////////////
+    //  Parcelable "contract" methods. //
+    /////////////////////////////////////
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeList(mDatasets);
+        parcel.writeParcelableArray(mSavableIds, 0);
+        parcel.writeBundle(mExtras);
+    }
+
+    private FillResponse(Parcel parcel) {
+        mDatasets = new ArrayList<>();
+        parcel.readList(mDatasets, null);
+        mSavableIds = parcel.readParcelableArray(null, AutoFillId.class);
+        mExtras = parcel.readBundle();
+    }
+
+    public static final Parcelable.Creator<FillResponse> CREATOR =
+            new Parcelable.Creator<FillResponse>() {
+        @Override
+        public FillResponse createFromParcel(Parcel source) {
+            return new FillResponse(source);
+        }
+
+        @Override
+        public FillResponse[] newArray(int size) {
+            return new FillResponse[size];
+        }
+    };
+}
diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java
new file mode 100644
index 0000000..772710e
--- /dev/null
+++ b/core/java/android/view/autofill/Helper.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.autofill;
+
+import android.os.Bundle;
+
+import java.util.Set;
+
+/** @hide */
+public final class Helper {
+
+    // TODO(b/33197203): set to false when stable
+    static final boolean DEBUG = true;
+    static final String REDACTED = "[REDACTED]";
+
+    static void append(StringBuilder builder, Bundle bundle) {
+        if (bundle == null) {
+            builder.append("N/A");
+        } else if (!DEBUG) {
+            builder.append(REDACTED);
+        } else {
+            final Set<String> keySet = bundle.keySet();
+            builder.append("[bundle with ").append(keySet.size()).append(" extras:");
+            for (String key : keySet) {
+                builder.append(' ').append(key).append('=').append(bundle.get(key)).append(',');
+            }
+            builder.append(']');
+        }
+    }
+
+    private Helper() {
+        throw new UnsupportedOperationException("contains static members only");
+    }
+}
diff --git a/core/java/android/view/autofill/VirtualViewDelegate.java b/core/java/android/view/autofill/VirtualViewDelegate.java
new file mode 100644
index 0000000..a19b4e5
--- /dev/null
+++ b/core/java/android/view/autofill/VirtualViewDelegate.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.autofill;
+
+import android.util.Log;
+import android.view.View;
+import android.view.ViewStructure;
+
+/**
+ * This class is the contract a client should implement to enable support of a
+ * virtual view hierarchy rooted at a given view for auto-fill purposes.
+ *
+ * <p>The view hierarchy is typically created through the
+ * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)} call and client
+ * add virtual children by calling {@link ViewStructure#newChild(int, int)} or
+ * {@link ViewStructure#asyncNewChild(int, int)}, where the client provides the {@code virtualId}
+ * of the children - the same {@code virtualId} is used in the methods of this class.
+ *
+ * <p>Objects of this class are typically created by overriding
+ * {@link View#getAutoFillVirtualViewDelegate(Callback)} and saving the passed callback, which must
+ * be notified upon changes on the hierarchy.
+ *
+ * <p>The main use case of these API is to enable custom views that draws its content - such as
+ * {@link android.webkit.WebView} providers - to support the AutoFill Framework:
+ *
+ * <ol>
+ *   <li>Client populates the virtual hierarchy on
+ * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)}
+ *   <li>Android System generates the proper {@link AutoFillId} - encapsulating the view and the
+ * virtual node ids - and pass it to the {@link android.service.autofill.AutoFillService}.
+ *   <li>The service uses the {@link AutoFillId} to populate the auto-fill {@link Dataset}s and pass
+ *   it back to the Android System.
+ *   <li>Android System uses the {@link AutoFillId} to find the proper custom view and calls
+ *   {@link #autoFill(int, AutoFillValue)} on that view passing the virtual id.
+ *   <li>This provider than finds the node in the hierarchy and auto-fills it.
+ * </ol>
+ *
+ */
+public abstract class VirtualViewDelegate {
+
+    // TODO(b/33197203): set to false once stable
+    private static final boolean DEBUG = true;
+
+    private static final String TAG = "VirtualViewDelegate";
+
+    /**
+     * Auto-fills a virtual view with the {@code value}.
+     *
+     * @param virtualId id identifying the virtual node inside the custom view.
+     * @param value value to be auto-filled.
+     */
+    public abstract void autoFill(int virtualId, AutoFillValue value);
+
+    /**
+     * Callback used to notify the AutoFill Framework of changes made on the view hierarchy while
+     * an {@link android.app.Activity} is being auto filled.
+     */
+    public abstract static class Callback {
+
+        /**
+         * Sent when the focus inside the hierarchy changed.
+         *
+         * <p>Typically callled twice - for the nodes that lost and gained focus.
+         *
+         * <p>This method should only be called when the change was not caused by the AutoFill
+         * Framework itselft (i.e, through {@link VirtualViewDelegate#autoFill(int, AutoFillValue)},
+         * but by external causes (for example, when the user changed the value through the view's
+         * UI).
+         *
+         * @param virtualId id of the node whose focus changed.
+         * @param hasFocus {@code true} when focus was gained, {@code false} when it was lost.
+         */
+        public void onFocusChanged(int virtualId, boolean hasFocus) {
+            if (DEBUG) Log.d(TAG, "onFocusChanged() for " + virtualId + ": " + hasFocus);
+        }
+
+        /**
+         * Sent when the value of a node was changed.
+         *
+         * <p>This method should only be called when the change was not caused by the AutoFill
+         * Framework itselft (i.e, through {@link VirtualViewDelegate#autoFill(int, AutoFillValue)},
+         * but by external causes (for example, when the user changed the value through the view's
+         * UI).
+         *
+         * @param virtualId id of the node whose value changed.
+         */
+        public void onValueChanged(int virtualId) {
+            if (DEBUG) Log.d(TAG, "onValueChanged() for" + virtualId);
+        }
+
+        /**
+         * Sent when nodes were removed (or had their ids changed) after the hierarchy has been
+         * committed to
+         * {@link View#onProvideAutoFillVirtualStructure(android.view.ViewStructure, int)}.
+         *
+         * <p>For example, when the view is rendering an {@code HTML} page, it should call this
+         * method when:
+         * <ul>
+         * <li>User navigated to another page and some (or all) nodes are gone.
+         * <li>The page's {@code DOM} was changed by {@code JavaScript} and some nodes moved (and
+         * are now identified by different ids).
+         * </ul>
+         *
+         * @param virtualIds id of the nodes that were removed.
+         */
+        public void onNodeRemoved(int... virtualIds) {
+            if (DEBUG) Log.d(TAG, "onNodeRemoved(): " + virtualIds);
+        }
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 8ecc42d..f98c099 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2515,8 +2515,8 @@
     }
 
     @Override
-    public void onProvideVirtualStructure(ViewStructure structure, int flags) {
-        mProvider.getViewDelegate().onProvideVirtualStructure(structure, flags);
+    public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
+        mProvider.getViewDelegate().onProvideAutoFillVirtualStructure(structure, flags);
     }
 
     /** @hide */
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 7b95180..dd1b0d2 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -312,7 +312,7 @@
         public void onProvideVirtualStructure(android.view.ViewStructure structure);
 
         @SuppressWarnings("unused")
-        public default void onProvideVirtualStructure(android.view.ViewStructure structure,
+        public default void onProvideAutoFillVirtualStructure(android.view.ViewStructure structure,
                 int flags) {
         }
 
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 3213a34..718070d 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -34,6 +34,8 @@
 import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
 
@@ -52,6 +54,7 @@
  * </p>
  */
 public abstract class CompoundButton extends Button implements Checkable {
+
     private boolean mChecked;
     private boolean mBroadcasting;
 
@@ -111,6 +114,7 @@
         applyButtonTint();
     }
 
+    @Override
     public void toggle() {
         setChecked(!mChecked);
     }
@@ -130,6 +134,7 @@
     }
 
     @ViewDebug.ExportedProperty
+    @Override
     public boolean isChecked() {
         return mChecked;
     }
@@ -139,6 +144,7 @@
      *
      * @param checked true to check the button, false to uncheck it
      */
+    @Override
     public void setChecked(boolean checked) {
         if (mChecked != checked) {
             mChecked = checked;
@@ -514,12 +520,15 @@
                     + " checked=" + checked + "}";
         }
 
-        public static final Parcelable.Creator<SavedState> CREATOR
-                = new Parcelable.Creator<SavedState>() {
+        @SuppressWarnings("hiding")
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            @Override
             public SavedState createFromParcel(Parcel in) {
                 return new SavedState(in);
             }
 
+            @Override
             public SavedState[] newArray(int size) {
                 return new SavedState[size];
             }
@@ -551,4 +560,16 @@
         super.encodeProperties(stream);
         stream.addProperty("checked", isChecked());
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        setChecked(value.getToggleValue());
+    }
+
+    @Override
+    public AutoFillType getAutoFillType() {
+        return AutoFillType.forToggle();
+    }
 }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 043eb34..af5c842 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -24,8 +24,10 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.accessibility.AccessibilityNodeInfo;
-
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillValue;
 
 /*
  * This is supposed to be a *very* thin veneer over TextView.
@@ -154,4 +156,26 @@
             info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
         }
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        final CharSequence text = value.getTextValue();
+
+        if (text == null) {
+            Log.w(VIEW_LOG_TAG, "EditText.autoFill(): no text on AutoFillValue");
+            return;
+        }
+        // TODO(b/33197203): once auto-fill is triggered by the IME, we'll need a new setText()
+        // or setAutoFillText() method on TextView to avoid re-triggering it.
+        setText(text);
+    }
+
+    @Override
+    public AutoFillType getAutoFillType() {
+        // TODO(b/33197203): ideally it should return a constant, but value returned by
+        // getInputType() can change.
+        return AutoFillType.forText(getInputType());
+    }
 }
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 54b5763..45fd9e6 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -16,12 +16,16 @@
 
 package android.widget;
 
+
 import android.annotation.IdRes;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillValue;
 
 import com.android.internal.R;
 
@@ -51,6 +55,7 @@
  *
  */
 public class RadioGroup extends LinearLayout {
+
     // holds the checked id; the selection is empty by default
     private int mCheckedId = -1;
     // tracks children radio buttons checked state
@@ -335,6 +340,7 @@
     }
 
     private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
+        @Override
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
             // prevents from infinite recursion
             if (mProtectFromCheckedChange) {
@@ -364,6 +370,7 @@
         /**
          * {@inheritDoc}
          */
+        @Override
         public void onChildViewAdded(View parent, View child) {
             if (parent == RadioGroup.this && child instanceof RadioButton) {
                 int id = child.getId();
@@ -384,6 +391,7 @@
         /**
          * {@inheritDoc}
          */
+        @Override
         public void onChildViewRemoved(View parent, View child) {
             if (parent == RadioGroup.this && child instanceof RadioButton) {
                 ((RadioButton) child).setOnCheckedChangeWidgetListener(null);
@@ -394,4 +402,22 @@
             }
         }
     }
+
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        final int index = value.getListValue();
+        final View child = getChildAt(index);
+        if (child == null) {
+            Log.w(VIEW_LOG_TAG, "RadioGroup.autoFill(): no child with index " + index);
+            return;
+        }
+        check(child.getId());
+    }
+
+    @Override
+    public AutoFillType getAutoFillType() {
+        return AutoFillType.forList();
+    }
 }
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index e629df9..a9257e6 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1404,10 +1404,19 @@
     }
 
     @Override
-    public void onProvideStructure(ViewStructure structure, int flags) {
-        super.onProvideStructure(structure, flags);
+    public void onProvideStructure(ViewStructure structure) {
+        super.onProvideStructure(structure);
+        onProvideAutoFillStructureForAssistOrAutoFill(structure);
+    }
 
-        // NOTE: current there is no difference for Assist (flags=0) or AutoFill (flags>0);
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+        onProvideAutoFillStructureForAssistOrAutoFill(structure);
+    }
+
+    // NOTE: currently there is no difference for Assist or AutoFill, so it doesn't take flags
+    private void onProvideAutoFillStructureForAssistOrAutoFill(ViewStructure structure) {
         CharSequence switchText = isChecked() ? mTextOn : mTextOff;
         if (!TextUtils.isEmpty(switchText)) {
             CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1961bf6..1ddf53d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -596,6 +596,7 @@
 
     private int mBreakStrategy;
     private int mHyphenationFrequency;
+    private boolean mJustify;
 
     private int mMaximum = Integer.MAX_VALUE;
     private int mMaxMode = LINES;
@@ -769,6 +770,7 @@
         String fontFeatureSettings = null;
         mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
         mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
+        mJustify = false;
 
         final Resources.Theme theme = context.getTheme();
 
@@ -3298,6 +3300,29 @@
     }
 
     /**
+     * Enables or disables full justification. The default value is false.
+     *
+     * @see #getJustify()
+     */
+    public void setJustify(boolean justify) {
+        mJustify = justify;
+        if (mLayout != null) {
+            nullLayouts();
+            requestLayout();
+            invalidate();
+        }
+    }
+
+    /**
+     * @return true if currently paragraph justification is enabled.
+     *
+     * @see #setJustify(boolean)
+     */
+    public boolean getJustify() {
+        return mJustify;
+    }
+
+    /**
      * Sets font feature settings. The format is the same as the CSS
      * font-feature-settings attribute:
      * <a href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
@@ -7170,6 +7195,7 @@
                         .setIncludePad(mIncludePad)
                         .setBreakStrategy(mBreakStrategy)
                         .setHyphenationFrequency(mHyphenationFrequency)
+                        .setJustify(mJustify)
                         .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
                 if (shouldEllipsize) {
                     builder.setEllipsize(mEllipsize)
@@ -7211,7 +7237,7 @@
         if (mText instanceof Spannable) {
             result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth,
                     alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad,
-                    mBreakStrategy, mHyphenationFrequency,
+                    mBreakStrategy, mHyphenationFrequency, mJustify,
                     getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth);
         } else {
             if (boring == UNKNOWN_BORING) {
@@ -7261,6 +7287,7 @@
                     .setIncludePad(mIncludePad)
                     .setBreakStrategy(mBreakStrategy)
                     .setHyphenationFrequency(mHyphenationFrequency)
+                    .setJustify(mJustify)
                     .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE);
             if (shouldEllipsize) {
                 builder.setEllipsize(effectiveEllipsize)
@@ -9391,11 +9418,23 @@
     }
 
     @Override
-    public void onProvideStructure(ViewStructure structure, int flags) {
-        super.onProvideStructure(structure, flags);
+    public void onProvideStructure(ViewStructure structure) {
+        super.onProvideStructure(structure);
+        onProvideAutoStructureForAssistOrAutoFill(structure, 0);
+    }
 
+    @Override
+    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
+        super.onProvideAutoFillStructure(structure, flags);
+        onProvideAutoStructureForAssistOrAutoFill(structure, flags);
+    }
+
+    private void onProvideAutoStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
+        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
+        // this method should take a boolean with the type of request.
         final boolean forAutoFillSave =
-                (flags & ASSIST_FLAG_NON_SANITIZED_TEXT) != 0;
+                (flags & AUTO_FILL_FLAG_TYPE_SAVE) != 0;
+
         final boolean isPassword = hasPasswordTransformationMethod()
                 || isPasswordInputType(getInputType());
         if (!isPassword || forAutoFillSave) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 293de3d..e1e0a21 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -85,6 +85,9 @@
      * file descriptor numbers that are to be closed by the child
      * (and replaced by /dev/null) after forking.  An integer value
      * of -1 in any entry in the array means "ignore this one".
+     * @param fdsToIgnore null-ok an array of ints, either null or holding
+     * one or more POSIX file descriptor numbers that are to be ignored
+     * in the file descriptor table check.
      * @param instructionSet null-ok the instruction set to use.
      * @param appDataDir null-ok the data directory of the app.
      *
@@ -93,11 +96,11 @@
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          String instructionSet, String appDataDir) {
+          int[] fdsToIgnore, String instructionSet, String appDataDir) {
         VM_HOOKS.preFork();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
-                  instructionSet, appDataDir);
+                  fdsToIgnore, instructionSet, appDataDir);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Trace.setTracingEnabled(true);
@@ -111,7 +114,7 @@
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          String instructionSet, String appDataDir);
+          int[] fdsToIgnore, String instructionSet, String appDataDir);
 
     /**
      * Special method to start the system server process. In addition to the
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 345350c..83e3cff 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -196,11 +196,14 @@
                 rlimits = parsedArgs.rlimits.toArray(intArray2d);
             }
 
+            int[] fdsToIgnore = null;
+
             if (parsedArgs.invokeWith != null) {
                 FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
                 childPipeFd = pipeFds[1];
                 serverPipeFd = pipeFds[0];
                 Os.fcntlInt(childPipeFd, F_SETFD, 0);
+                fdsToIgnore = new int[] { childPipeFd.getInt$(), serverPipeFd.getInt$() };
             }
 
             /**
@@ -233,7 +236,7 @@
 
             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                     parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
-                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
+                    parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                     parsedArgs.appDataDir);
         } catch (ErrnoException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index b41ef29..32ce0fe 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -86,7 +86,7 @@
             mCallbacks.remove(callback);
         }
     }
-    
+
     public SurfaceHolder.Callback[] getCallbacks() {
         if (mHaveGottenCallbacks) {
             return mGottenCallbacks;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 4f7b106..0185e30 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -562,8 +562,6 @@
             }
             case DO_COMMIT_CONTENT: {
                 final int flags = msg.arg1;
-                final boolean grantUriPermission =
-                        (flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0;
                 SomeArgs args = (SomeArgs) msg.obj;
                 try {
                     InputConnection ic = getInputConnection();
@@ -579,22 +577,8 @@
                         args.callback.setCommitContentResult(false, args.seq);
                         return;
                     }
-                    if (grantUriPermission) {
-                        try {
-                            inputContentInfo.requestPermission();
-                        } catch (Exception e) {
-                            Log.e(TAG, "InputConnectionInfo.requestPermission() failed", e);
-                            args.callback.setCommitContentResult(false, args.seq);
-                            return;
-                        }
-                    }
                     final boolean result =
                             ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2);
-                    // If this request is not handled, then there is no reason to keep the URI
-                    // permission.
-                    if (grantUriPermission && !result) {
-                        inputContentInfo.releasePermission();
-                    }
                     args.callback.setCommitContentResult(result, args.seq);
                 } catch (RemoteException e) {
                     Log.w(TAG, "Got RemoteException calling commitContent", e);
diff --git a/core/java/com/android/internal/view/SurfaceCallbackHelper.java b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
new file mode 100644
index 0000000..5b6a82c
--- /dev/null
+++ b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.os.RemoteException;
+import android.view.IWindow;
+import android.view.IWindowSession;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+
+public class SurfaceCallbackHelper {
+    IWindowSession mSession;
+    IWindow.Stub mWindow;
+
+    int mFinishDrawingCollected = 0;
+    int mFinishDrawingExpected = 0;
+
+    private Runnable mFinishDrawingRunnable = new Runnable() {
+            @Override
+            public void run() {
+                synchronized (SurfaceCallbackHelper.this) {
+                    mFinishDrawingCollected++;
+                    if (mFinishDrawingCollected < mFinishDrawingExpected) {
+                        return;
+                    }
+                    try {
+                        mSession.finishDrawing(mWindow);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+    };
+
+    public SurfaceCallbackHelper(IWindowSession session,
+            IWindow.Stub window) {
+        mSession = session;
+        mWindow = window;
+    }
+
+    public void dispatchSurfaceRedrawNeededAsync(SurfaceHolder holder, SurfaceHolder.Callback callbacks[]) {
+        if (callbacks == null || callbacks.length == 0) {
+            try {
+                mSession.finishDrawing(mWindow);
+            } catch (RemoteException e) {
+            }
+            return;
+        }
+
+        synchronized (this) {
+            mFinishDrawingExpected = callbacks.length;
+            mFinishDrawingCollected = 0;
+        }
+
+        for (SurfaceHolder.Callback c : callbacks) {
+            if (c instanceof SurfaceHolder.Callback2) {
+                ((SurfaceHolder.Callback2) c).surfaceRedrawNeededAsync(
+                        holder, mFinishDrawingRunnable);
+            } else {
+                mFinishDrawingRunnable.run();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
index aa6348e..dcb7874 100644
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
+++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
@@ -33,7 +33,9 @@
 #include "HarfBuzzNGFaceSkia.h"
 
 #include <stdlib.h>
-#include <cutils/log.h>
+
+#include <log/log.h>
+
 #include <SkPaint.h>
 #include <SkPath.h>
 #include <SkPoint.h>
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index aa4570f..14d7e81 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -16,32 +16,32 @@
 
 #define LOG_TAG "android.os.Debug"
 
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <malloc.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <time.h>
 #include <sys/time.h>
-#include <errno.h>
-#include <assert.h>
-#include <ctype.h>
-#include <malloc.h>
+#include <time.h>
+#include <unistd.h>
 
 #include <iomanip>
 #include <string>
 
-#include "jni.h"
+#include <android-base/stringprintf.h>
+#include <cutils/debugger.h>
+#include <log/log.h>
+#include <utils/misc.h>
+#include <utils/String8.h>
 
-#include "android-base/stringprintf.h"
-#include "cutils/debugger.h"
-#include "cutils/log.h"
 #include "JNIHelp.h"
-#include "memtrack/memtrack.h"
-#include "memunreachable/memunreachable.h"
-#include "utils/misc.h"
-#include "utils/String8.h"
+#include "jni.h"
+#include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
 
 namespace android
 {
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index ea893f0..de91f70 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -19,15 +19,14 @@
 
 #include <inttypes.h>
 
+#include <cutils/trace.h>
+#include <utils/String8.h>
+#include <log/log.h>
+
 #include <JNIHelp.h>
 #include <ScopedUtfChars.h>
 #include <ScopedStringChars.h>
 
-#include <utils/String8.h>
-
-#include <cutils/trace.h>
-#include <cutils/log.h>
-
 namespace android {
 
 static void sanitizeString(String8& utf8Chars) {
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index 02fa872..c05ef26 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -54,7 +54,8 @@
 // hyphenFrequency)
 static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length,
         jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth,
-        jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency) {
+        jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency,
+        jboolean isJustified) {
     minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr);
     b->resize(length);
     env->GetCharArrayRegion(text, 0, length, b->buffer());
@@ -68,6 +69,7 @@
     }
     b->setStrategy(static_cast<minikin::BreakStrategy>(strategy));
     b->setHyphenationFrequency(static_cast<minikin::HyphenationFrequency>(hyphenFrequency));
+    b->setJustified(isJustified);
 }
 
 static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
@@ -190,7 +192,7 @@
     {"nFinishBuilder", "(J)V", (void*) nFinishBuilder},
     {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;I)J", (void*) nLoadHyphenator},
     {"nSetLocale", "(JLjava/lang/String;J)V", (void*) nSetLocale},
-    {"nSetupParagraph", "(J[CIFIF[IIII)V", (void*) nSetupParagraph},
+    {"nSetupParagraph", "(J[CIFIF[IIIIZ)V", (void*) nSetupParagraph},
     {"nSetIndents", "(J[I)V", (void*) nSetIndents},
     {"nAddStyleRun", "(JJJIIZ)F", (void*) nAddStyleRun},
     {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun},
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 5559d48..abcd1e7 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -29,19 +29,19 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <utils/Atomic.h>
 #include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
 #include <binder/IPCThreadState.h>
-#include <utils/Log.h>
-#include <utils/SystemClock.h>
-#include <utils/List.h>
-#include <utils/KeyedVector.h>
-#include <log/logger.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/threads.h>
+#include <log/log.h>
+#include <utils/Atomic.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/Log.h>
 #include <utils/String8.h>
+#include <utils/SystemClock.h>
+#include <utils/threads.h>
 
 #include <ScopedUtfChars.h>
 #include <ScopedLocalRef.h>
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 7719e31..20dfe78 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -21,7 +21,7 @@
 #include <android-base/macros.h>
 #include <assert.h>
 #include <cutils/properties.h>
-#include <log/logger.h>               // For LOGGER_ENTRY_MAX_PAYLOAD.
+#include <log/log.h>               // For LOGGER_ENTRY_MAX_PAYLOAD.
 #include <utils/Log.h>
 #include <utils/String8.h>
 
diff --git a/core/jni/android_util_jar_StrictJarFile.cpp b/core/jni/android_util_jar_StrictJarFile.cpp
index 2e31c8b..4f1f926 100644
--- a/core/jni/android_util_jar_StrictJarFile.cpp
+++ b/core/jni/android_util_jar_StrictJarFile.cpp
@@ -20,13 +20,14 @@
 #include <memory>
 #include <string>
 
+#include <log/log.h>
+
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
 #include "jni.h"
 #include "ziparchive/zip_archive.h"
-#include "cutils/log.h"
 
 namespace android {
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index cc7b958..070a2d9 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -43,6 +43,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include "android-base/logging.h"
 #include <cutils/fs.h>
 #include <cutils/multiuser.h>
 #include <cutils/sched_policy.h>
@@ -440,6 +441,22 @@
 // The list of open zygote file descriptors.
 static FileDescriptorTable* gOpenFdTable = NULL;
 
+static void FillFileDescriptorVector(JNIEnv* env,
+                                     jintArray java_fds,
+                                     std::vector<int>* fds) {
+  CHECK(fds != nullptr);
+  if (java_fds != nullptr) {
+    ScopedIntArrayRO ar(env, java_fds);
+    if (ar.get() == nullptr) {
+      RuntimeAbort(env, __LINE__, "Bad fd array");
+    }
+    fds->reserve(ar.size());
+    for (size_t i = 0; i < ar.size(); ++i) {
+      fds->push_back(ar[i]);
+    }
+  }
+}
+
 // Utility routine to fork zygote and specialize the child process.
 static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                      jint debug_flags, jobjectArray javaRlimits,
@@ -447,6 +464,7 @@
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
                                      bool is_system_server, jintArray fdsToClose,
+                                     jintArray fdsToIgnore,
                                      jstring instructionSet, jstring dataDir) {
   SetSigChldHandler();
 
@@ -471,12 +489,14 @@
   // If this is the first fork for this zygote, create the open FD table.
   // If it isn't, we just need to check whether the list of open files has
   // changed (and it shouldn't in the normal case).
+  std::vector<int> fds_to_ignore;
+  FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
   if (gOpenFdTable == NULL) {
-    gOpenFdTable = FileDescriptorTable::Create();
+    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
     if (gOpenFdTable == NULL) {
       RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
     }
-  } else if (!gOpenFdTable->Restat()) {
+  } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
     RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
   }
 
@@ -646,7 +666,9 @@
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint debug_flags, jobjectArray rlimits,
         jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
+        jintArray fdsToClose,
+        jintArray fdsToIgnore,
+        jstring instructionSet, jstring appDataDir) {
     jlong capabilities = 0;
 
     // Grant CAP_WAKE_ALARM to the Bluetooth process.
@@ -681,7 +703,7 @@
 
     return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
             rlimits, capabilities, capabilities, mount_external, se_info,
-            se_name, false, fdsToClose, instructionSet, appDataDir);
+            se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -692,7 +714,7 @@
                                       debug_flags, rlimits,
                                       permittedCapabilities, effectiveCapabilities,
                                       MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
-                                      NULL, NULL);
+                                      NULL, NULL, NULL);
   if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -759,7 +781,7 @@
 
 static const JNINativeMethod gMethods[] = {
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 969d336f3..59a536b 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -381,7 +381,7 @@
 }
 
 // static
-FileDescriptorTable* FileDescriptorTable::Create() {
+FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
   DIR* d = opendir(kFdPath);
   if (d == NULL) {
     ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
@@ -396,6 +396,10 @@
     if (fd == -1) {
       continue;
     }
+    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
+      ALOGI("Ignoring open file descriptor %d", fd);
+      continue;
+    }
 
     FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
     if (info == NULL) {
@@ -414,7 +418,7 @@
   return new FileDescriptorTable(open_fd_map);
 }
 
-bool FileDescriptorTable::Restat() {
+bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
   std::set<int> open_fds;
 
   // First get the list of open descriptors.
@@ -431,6 +435,10 @@
     if (fd == -1) {
       continue;
     }
+    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
+      ALOGI("Ignoring open file descriptor %d", fd);
+      continue;
+    }
 
     open_fds.insert(fd);
   }
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index 9e3afd9..03298c3 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -122,9 +122,9 @@
   // Creates a new FileDescriptorTable. This function scans
   // /proc/self/fd for the list of open file descriptors and collects
   // information about them. Returns NULL if an error occurs.
-  static FileDescriptorTable* Create();
+  static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore);
 
-  bool Restat();
+  bool Restat(const std::vector<int>& fds_to_ignore);
 
   // Reopens all file descriptors that are contained in the table. Returns true
   // if all descriptors were successfully re-opened or detached, and false if an
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9cbb8c3..89581bb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1049,6 +1049,16 @@
          Must be in the range specified by minimum and maximum. -->
     <integer name="config_screenBrightnessSettingDefault">102</integer>
 
+    <!-- Default screen brightness for VR setting. -->
+    <integer name="config_screenBrightnessForVrSettingDefault">86</integer>
+
+    <!-- Minimum screen brightness setting allowed for VR. Device panels start increasing pulse
+         width as brightness decreases below this theshold. -->
+    <integer name="config_screenBrightnessForVrSettingMinimum">79</integer>
+
+    <!-- Maximum screen brightness setting allowed for VR. -->
+    <integer name="config_screenBrightnessForVrSettingMaximum">255</integer>
+
     <!-- Screen brightness used to dim the screen while dozing in a very low power state.
          May be less than the minimum allowed brightness setting
          that can be set by the user. -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 5c165e6..5547706 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -129,4 +129,6 @@
   <item type="id" name="remote_input_tag" />
 
   <item type="id" name="cross_task_transition" />
+
+  <item type="id" name="accessibilityActionClickOnClickableSpan" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b7f5a9b..b0d64577 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2868,17 +2868,6 @@
     <!-- If there is ever a ringtone set for some setting, but that ringtone can no longer be resolved, t his is shown instead.  For example, if the ringtone was on a SD card and it had been removed, this woudl be shown for ringtones on that SD card. -->
     <string name="ringtone_unknown">Unknown</string>
 
-    <!-- A notification is shown when there are open wireless networks nearby.  This is the notification's title. -->
-    <plurals name="wifi_available">
-        <item quantity="one">Wi-Fi network available</item>
-        <item quantity="other">Wi-Fi networks available</item>
-    </plurals>
-    <!-- A notification is shown when there are open wireless networks nearby.  This is the notification's message. -->
-    <plurals name="wifi_available_detailed">
-        <item quantity="one">Open Wi-Fi network available</item>
-        <item quantity="other">Open Wi-Fi networks available</item>
-    </plurals>
-
     <!-- A notification is shown when a wifi captive portal network is detected.  This is the notification's title. -->
     <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cd3c0e3..f44b039 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -213,6 +213,7 @@
   <java-symbol type="id" name="selection_start_handle" />
   <java-symbol type="id" name="selection_end_handle" />
   <java-symbol type="id" name="insertion_handle" />
+  <java-symbol type="id" name="accessibilityActionClickOnClickableSpan" />
 
   <java-symbol type="attr" name="actionModeShareDrawable" />
   <java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -1803,6 +1804,9 @@
   <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" />
   <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" />
   <java-symbol type="integer" name="config_screenBrightnessSettingDefault" />
+  <java-symbol type="integer" name="config_screenBrightnessForVrSettingDefault" />
+  <java-symbol type="integer" name="config_screenBrightnessForVrSettingMaximum" />
+  <java-symbol type="integer" name="config_screenBrightnessForVrSettingMinimum" />
   <java-symbol type="integer" name="config_screenBrightnessDark" />
   <java-symbol type="integer" name="config_screenBrightnessDim" />
   <java-symbol type="integer" name="config_screenBrightnessDoze" />
@@ -1816,8 +1820,6 @@
   <java-symbol type="layout" name="safe_mode" />
   <java-symbol type="layout" name="simple_list_item_2_single_choice" />
   <java-symbol type="layout" name="app_error_dialog" />
-  <java-symbol type="plurals" name="wifi_available" />
-  <java-symbol type="plurals" name="wifi_available_detailed" />
   <java-symbol type="string" name="accessibility_binding_label" />
   <java-symbol type="string" name="adb_active_notification_message" />
   <java-symbol type="string" name="adb_active_notification_title" />
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 4699fd5..a0a9e01 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -33,7 +33,9 @@
     mockito-target-minus-junit4 \
     espresso-core \
     ub-uiautomator \
-    platform-test-annotations
+    platform-test-annotations \
+    compatibility-device-util
+
 LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
 LOCAL_PACKAGE_NAME := FrameworksCoreTests
 
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index e3a85b5..504541d 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -55,6 +55,8 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_DREAM_STATE" />
+    <uses-permission android:name="android.permission.WRITE_DREAM_STATE" />
     <uses-permission android:name="android.permission.READ_LOGS"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_SMS"/>
@@ -831,14 +833,14 @@
             </intent-filter>
         </activity>
 
-	    <activity android:name="android.widget.listview.ListManagedCursor" android:label="ListManagedCursor">
+      <activity android:name="android.widget.listview.ListManagedCursor" android:label="ListManagedCursor">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
 
-	    <activity android:name="android.widget.listview.ListWithEmptyView" android:label="ListWithEmptyView">
+      <activity android:name="android.widget.listview.ListWithEmptyView" android:label="ListWithEmptyView">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
@@ -1331,6 +1333,27 @@
             </meta-data>
         </service>
 
+        <activity
+            android:name="android.print.mockservice.SettingsActivity"
+            android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
+            android:exported="true">
+        </activity>
+
+        <activity
+            android:name="android.os.TestVrActivity"
+            android:enableVrMode="com.android.frameworks.coretests/android.os.TestVrActivity$TestVrListenerService">
+        </activity>
+
+        <service android:name="android.os.TestVrActivity$TestVrListenerService"
+            android:exported="true"
+            android:enabled="true"
+            android:label="Test Vr Listener Service"
+            android:permission="android.permission.BIND_VR_LISTENER_SERVICE">
+            <intent-filter>
+              <action android:name="android.service.vr.VrListenerService" />
+            </intent-filter>
+        </service>
+
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/core/tests/coretests/src/android/os/PowerManagerVrTest.java b/core/tests/coretests/src/android/os/PowerManagerVrTest.java
new file mode 100644
index 0000000..e01e5fa
--- /dev/null
+++ b/core/tests/coretests/src/android/os/PowerManagerVrTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.os;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.service.dreams.IDreamManager;
+import android.service.dreams.DreamService;
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Tests dream aspects of PowerManager.
+ */
+@MediumTest
+public class PowerManagerVrTest extends ActivityInstrumentationTestCase2<TestVrActivity> {
+    private PowerManager mPm;
+    private IDreamManager mDm;
+    private String mOldVrListener;
+
+    public PowerManagerVrTest() {
+        super(TestVrActivity.class);
+    }
+
+    /**
+     * Setup any common data for the upcoming tests.
+     */
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        Context context = getInstrumentation().getTargetContext();
+        mPm = (PowerManager) getInstrumentation().getTargetContext().getSystemService(
+                Context.POWER_SERVICE);
+        mDm = IDreamManager.Stub.asInterface(
+                ServiceManager.getService(DreamService.DREAM_SERVICE));
+
+        mOldVrListener = setTestVrListener(new ComponentName(
+                context, TestVrActivity.TestVrListenerService.class).flattenToString());
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        if (mDm != null) {
+            mDm.awaken();  // Don't leave the device in the dream state.
+        }
+
+        setTestVrListener(mOldVrListener);
+    }
+
+    /**
+     * Confirm that the setup is good.
+     *
+     * @throws Exception
+     */
+    @SmallTest
+    public void testPreconditions() throws Exception {
+        assertNotNull(mPm);
+        assertNotNull(mDm);
+    }
+
+    /**
+     * Confirm that the system prevents napping while in VR.
+     * Dreaming is controlled by PowerManager, but we use dreamManager to access those features
+     * in order to not require DEVICE_POWER permissions which other tests expect not to have.
+     *
+     * @throws Exception
+     */
+    @SmallTest
+    public void testNap() throws Exception {
+        // For dream to work, we need to wake up the system
+        wakeUpDevice();
+
+        mDm.dream();
+        waitForDreamState(true);
+        assertTrue(mDm.isDreaming());
+        mDm.awaken();
+
+        // awaken() is not immediate so we have to wait for dreaming to stop
+        // before continuing with the test.
+        waitForDreamState(false);
+
+        // set VR Mode to true by starting our VR Activity, then retest the dream.
+        TestVrActivity activity = getActivity();
+        assertTrue(activity.waitForActivityStart());
+
+        try {
+            mDm.dream();
+            waitForDreamState(true);  // wait for dream to turn true with a timeout
+            assertFalse(mDm.isDreaming()); // ensure dream is still false after waiting.
+            mDm.awaken();
+        } finally {
+            activity.finish();
+        }
+    }
+
+    /**
+     * Waits synchronously for the system to be set to the specified dream state.
+     */
+    private void waitForDreamState(boolean isDreaming) throws Exception {
+        final int MAX_ATTEMPTS = 10;
+        final int WAIT_TIME_PER_ATTEMPT_MILLIS = 100;
+        for (int i = 0; i < MAX_ATTEMPTS; i++) {
+          if (mDm.isDreaming() == isDreaming) {
+            break;
+          }
+          Thread.sleep(WAIT_TIME_PER_ATTEMPT_MILLIS);
+        }
+    }
+
+    private void wakeUpDevice() {
+        PowerManager.WakeLock wl = mPm.newWakeLock(
+                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
+                | PowerManager.ON_AFTER_RELEASE, "FULL_WAKE_LOCK");
+        wl.acquire();
+        wl.release();
+    }
+
+    /**
+     * Sets a new value for the enabled VrListenerService and returns the previous value.
+     */
+    private String setTestVrListener(String newValue) {
+        final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
+        Context context = getInstrumentation().getTargetContext();
+        ContentResolver cr = context.getContentResolver();
+        String oldVrListeners = Settings.Secure.getString(cr, ENABLED_VR_LISTENERS);
+        Settings.Secure.putString(cr, ENABLED_VR_LISTENERS, newValue);
+        return oldVrListeners;
+    }
+}
diff --git a/core/tests/coretests/src/android/os/TestVrActivity.java b/core/tests/coretests/src/android/os/TestVrActivity.java
new file mode 100644
index 0000000..33ff164
--- /dev/null
+++ b/core/tests/coretests/src/android/os/TestVrActivity.java
@@ -0,0 +1,59 @@
+/*
+ * 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.os;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.service.vr.VrListenerService;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An activity for enabling/disabling VrMode.
+ */
+public class TestVrActivity extends Activity {
+    private CountDownLatch mLatch;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mLatch = new CountDownLatch(1);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mLatch.countDown();
+    }
+
+    public static class TestVrListenerService extends VrListenerService {
+        @Override
+        public void onCreate() {
+            super.onCreate();
+        }
+    }
+
+    public boolean waitForActivityStart() {
+        boolean result = false;
+        try {
+            result = mLatch.await(2L, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+        }
+        return result;
+    }
+}
diff --git a/core/tests/coretests/src/android/view/ViewInvalidateTest.java b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
new file mode 100644
index 0000000..4db70ec
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static junit.framework.Assert.assertFalse;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.LargeTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.widget.FrameLayout;
+
+import com.android.compatibility.common.util.WidgetTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test of invalidates, drawing, and the flags that support them
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class ViewInvalidateTest {
+    @Rule
+    public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
+
+    private static final int INVAL_TEST_FLAG_MASK = View.PFLAG_DIRTY
+            | View.PFLAG_DIRTY_OPAQUE
+            | View.PFLAG_DRAWN
+            | View.PFLAG_DRAWING_CACHE_VALID
+            | View.PFLAG_INVALIDATED
+            | View.PFLAG_DRAW_ANIMATION;
+
+    @Before
+    public void setup() throws Throwable {
+        // separate runnable to initialize, so ref is safe to pass to runOnMainAndDrawSync
+        mActivityRule.runOnUiThread(() -> {
+            mParent = new FrameLayout(getContext());
+            mChild = new View(getContext());
+        });
+
+        // attached view is drawn once
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+            mParent.addView(mChild);
+            getActivity().setContentView(mParent);
+
+            // 'invalidated', but not yet drawn
+            validateInvalFlags(mChild, View.PFLAG_INVALIDATED);
+        });
+    }
+
+    @After
+    public void teardown() {
+        // ensure we don't share views between tests
+        mParent = null;
+        mChild = null;
+    }
+
+    Context getContext() {
+        return InstrumentationRegistry.getTargetContext();
+    }
+
+    Activity getActivity() {
+        return mActivityRule.getActivity();
+    }
+
+    private ViewGroup mParent;
+    private View mChild;
+
+    private static void validateInvalFlags(View view, int... expectedFlagArray) {
+        int expectedFlags = 0;
+        for (int expectedFlag : expectedFlagArray) {
+            expectedFlags |= expectedFlag;
+        }
+
+        final int observedFlags = view.mPrivateFlags & INVAL_TEST_FLAG_MASK;
+        assertEquals(String.format("expect %x, observed %x", expectedFlags, observedFlags),
+                expectedFlags, observedFlags);
+    }
+
+    private static ViewRootImpl getViewRoot(View view) {
+        ViewParent parent = view.getParent();
+        while (parent != null) {
+            if (parent instanceof ViewRootImpl) {
+                return (ViewRootImpl) parent;
+            }
+            parent = parent.getParent();
+        }
+        return null;
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInvalidate_behavior() throws Throwable {
+        validateInvalFlags(mChild,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+        validateInvalFlags(mParent,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+        assertFalse(getViewRoot(mParent).mTraversalScheduled);
+
+        mChild.invalidate();
+
+        // no longer drawn, is now invalidated
+        validateInvalFlags(mChild,
+                View.PFLAG_DIRTY,
+                View.PFLAG_INVALIDATED);
+
+        // parent drawing cache no longer valid, marked dirty
+        validateInvalFlags(mParent,
+                View.PFLAG_DRAWN,
+                View.PFLAG_DIRTY);
+        assertTrue(getViewRoot(mParent).mTraversalScheduled);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInvalidate_false() {
+        // Invalidate makes it invalid
+        validateInvalFlags(mChild,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+
+        mChild.invalidate(/*don't invalidate cache*/ false);
+
+        // drawn is cleared, dirty set, nothing else changed
+        validateInvalFlags(mChild,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DIRTY);
+    }
+
+    @Test
+    public void testInvalidate_simple() throws Throwable {
+        // simple invalidate, which marks the view invalid
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+            validateInvalFlags(mChild,
+                    View.PFLAG_DRAWING_CACHE_VALID,
+                    View.PFLAG_DRAWN);
+
+            mChild.invalidate();
+
+            validateInvalFlags(mChild,
+                    View.PFLAG_DIRTY,
+                    View.PFLAG_INVALIDATED);
+        });
+
+        // after draw pass, view has drawn, no longer invalid
+        mActivityRule.runOnUiThread(() -> {
+            validateInvalFlags(mChild,
+                    View.PFLAG_DRAWING_CACHE_VALID,
+                    View.PFLAG_DRAWN);
+        });
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInvalidate_manualUpdateDisplayList() {
+        // Invalidate makes it invalid
+        validateInvalFlags(mChild,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+
+        mChild.invalidate();
+        validateInvalFlags(mChild,
+                View.PFLAG_DIRTY,
+                View.PFLAG_INVALIDATED);
+
+        // updateDisplayListIfDirty makes it valid again, but invalidate still set,
+        // since it's cleared by View#draw(canvas, parent, drawtime)
+        mChild.updateDisplayListIfDirty();
+            validateInvalFlags(mChild,
+                    View.PFLAG_DRAWING_CACHE_VALID,
+                    View.PFLAG_DRAWN,
+                    View.PFLAG_INVALIDATED);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInvalidateChild_simple() {
+        validateInvalFlags(mParent,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+        assertFalse(getViewRoot(mParent).mTraversalScheduled);
+
+        mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+        validateInvalFlags(mParent,
+                View.PFLAG_DIRTY,
+                View.PFLAG_DRAWN);
+        assertTrue(getViewRoot(mParent).mTraversalScheduled);
+    }
+
+    @Test
+    public void testInvalidateChild_childHardwareLayer() throws Throwable {
+        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> {
+            // do in runnable, so tree won't be dirty
+            mChild.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+        });
+
+        mActivityRule.runOnUiThread(() -> {
+            validateInvalFlags(mParent,
+                    View.PFLAG_DRAWING_CACHE_VALID,
+                    View.PFLAG_DRAWN);
+
+            mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+            validateInvalFlags(mParent,
+                    View.PFLAG_DIRTY,
+                    View.PFLAG_DRAWN,
+                    View.PFLAG_INVALIDATED);
+        });
+    }
+
+    @UiThreadTest
+    @Test
+    public void testInvalidateChild_legacyAnimation() throws Throwable {
+        mChild.mPrivateFlags |= View.PFLAG_DRAW_ANIMATION;
+
+        validateInvalFlags(mChild,
+                View.PFLAG_DRAW_ANIMATION,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+        validateInvalFlags(mParent,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+        assertFalse(getViewRoot(mParent).mIsAnimating);
+
+        mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1));
+
+        validateInvalFlags(mChild,
+                View.PFLAG_DRAW_ANIMATION,
+                View.PFLAG_DRAWING_CACHE_VALID,
+                View.PFLAG_DRAWN);
+        validateInvalFlags(mParent,
+                View.PFLAG_DIRTY,
+                View.PFLAG_DRAW_ANIMATION, // carried up to parent
+                View.PFLAG_DRAWN);
+        assertTrue(getViewRoot(mParent).mIsAnimating);
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java b/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java
new file mode 100644
index 0000000..1e55fb1
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.view.ViewGroup.OnHierarchyChangeListener;
+
+import com.android.frameworks.coretests.R;
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for AppWidgetHostView
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AppWidgetHostViewTest {
+
+    @Rule
+    public final ExpectedException exception = ExpectedException.none();
+
+    private Context mContext;
+    private String mPackage;
+    private AppWidgetHostView mHostView;
+
+    private ViewAddListener mViewAddListener;
+    private RemoteViews mViews;
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getContext();
+        mPackage = mContext.getPackageName();
+        mHostView = new AppWidgetHostView(mContext);
+        mHostView.setAppWidget(0, AppWidgetManager.getInstance(
+                mContext).getInstalledProviders().get(0));
+
+        mViewAddListener = new ViewAddListener();
+        mHostView.setOnHierarchyChangeListener(mViewAddListener);
+
+        mViews = new RemoteViews(mPackage, R.layout.remote_views_test);
+    }
+
+    @Test
+    public void syncInflation() {
+        mHostView.updateAppWidget(mViews);
+        assertNotNull(mHostView.findViewById(R.id.image));
+    }
+
+    @Test
+    public void asyncInflation() throws Exception {
+        RunnableList executor = new RunnableList();
+        mHostView.setAsyncExecutor(executor);
+
+        mHostView.updateAppWidget(mViews);
+        assertNull(mHostView.findViewById(R.id.image));
+
+        // Task queued.
+        assertEquals(1, executor.size());
+
+        // Execute the pending task
+        executor.get(0).run();
+        mViewAddListener.addLatch.await();
+        assertNotNull(mHostView.findViewById(R.id.image));
+    }
+
+    @Test
+    public void asyncInflation_cancelled() throws Exception {
+        RunnableList executor = new RunnableList();
+        mHostView.setAsyncExecutor(executor);
+
+        mHostView.updateAppWidget(mViews.clone());
+        mHostView.updateAppWidget(mViews.clone());
+        assertNull(mHostView.findViewById(R.id.image));
+
+        // Tasks queued.
+        assertEquals(2, executor.size());
+        // First task cancelled
+        assertTrue(((Future) executor.get(0)).isCancelled());
+
+        // Execute the pending task
+        executor.get(0).run();
+        executor.get(1).run();
+        mViewAddListener.addLatch.await();
+        assertNotNull(mHostView.findViewById(R.id.image));
+    }
+
+    private static class RunnableList extends ArrayList<Runnable> implements Executor {
+
+        @Override
+        public void execute(Runnable runnable) {
+            add(runnable);
+        }
+    }
+
+    private class ViewAddListener implements OnHierarchyChangeListener {
+
+        public final CountDownLatch addLatch = new CountDownLatch(1);
+
+
+        @Override
+        public void onChildViewAdded(View parent, View child) {
+            addLatch.countDown();
+        }
+
+        @Override
+        public void onChildViewRemoved(View parent, View child) {
+        }
+    }
+}
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index ba4a4ff..76a430e 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -16,14 +16,13 @@
 
 #define LOG_TAG "backup_data"
 
-#include <androidfw/BackupHelpers.h>
-#include <utils/ByteOrder.h>
-
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 
-#include <cutils/log.h>
+#include <androidfw/BackupHelpers.h>
+#include <log/log.h>
+#include <utils/ByteOrder.h>
 
 namespace android {
 
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index 78e9d91..8bfe2b6 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -18,23 +18,22 @@
 
 #include <androidfw/BackupHelpers.h>
 
-#include <utils/KeyedVector.h>
-#include <utils/ByteOrder.h>
-#include <utils/String8.h>
-
 #include <errno.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/stat.h>
-#include <sys/time.h>  // for utimes
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>  // for utimes
+#include <sys/uio.h>
 #include <unistd.h>
 #include <utime.h>
-#include <fcntl.h>
 #include <zlib.h>
 
-#include <cutils/log.h>
+#include <log/log.h>
+#include <utils/ByteOrder.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
 
 namespace android {
 
diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h
index 8a2979a..f543565 100644
--- a/libs/androidfw/include/androidfw/CursorWindow.h
+++ b/libs/androidfw/include/androidfw/CursorWindow.h
@@ -17,11 +17,11 @@
 #ifndef _ANDROID__DATABASE_WINDOW_H
 #define _ANDROID__DATABASE_WINDOW_H
 
-#include <cutils/log.h>
 #include <stddef.h>
 #include <stdint.h>
 
 #include <binder/Parcel.h>
+#include <log/log.h>
 #include <utils/String8.h>
 
 #if LOG_NDEBUG
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 9d5860c..f5bb821 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -142,7 +142,7 @@
 }
 
 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
-    uint32_t dirtyMask;
+    uint32_t dirtyMask = 0;
     AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
     auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 6d5833b..2b4fe17 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -16,7 +16,7 @@
 
 #include "DamageAccumulator.h"
 
-#include <cutils/log.h>
+#include <log/log.h>
 
 #include "RenderNode.h"
 #include "utils/MathUtils.h"
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 700642e..d180ba5 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -13,16 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #include <DeviceInfo.h>
 
 #include "Extensions.h"
 
-#include <GLES2/gl2.h>
-#include <log/log.h>
-
 #include <thread>
 #include <mutex>
 
+#include <log/log.h>
+
+#include <GLES2/gl2.h>
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h
index bfb1bf1..352f3d7 100644
--- a/libs/hwui/GpuMemoryTracker.h
+++ b/libs/hwui/GpuMemoryTracker.h
@@ -15,10 +15,11 @@
  */
 #pragma once
 
-#include <cutils/log.h>
 #include <pthread.h>
 #include <ostream>
 
+#include <log/log.h>
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index f94a22d..d740c03 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -16,10 +16,11 @@
 
 #include "Interpolator.h"
 
-#include "utils/MathUtils.h"
-
 #include <algorithm>
-#include <cutils/log.h>
+
+#include <log/log.h>
+
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index ed6b211..0a9bf54 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -15,19 +15,21 @@
  */
 #include "JankTracker.h"
 
-#include "Properties.h"
-#include "utils/TimeUtils.h"
-
-#include <algorithm>
-#include <cutils/ashmem.h>
-#include <cutils/log.h>
-#include <cstdio>
 #include <errno.h>
 #include <inttypes.h>
-#include <limits>
+
+#include <algorithm>
 #include <cmath>
+#include <cstdio>
+#include <limits>
 #include <sys/mman.h>
 
+#include <cutils/ashmem.h>
+#include <log/log.h>
+
+#include "Properties.h"
+#include "utils/TimeUtils.h"
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
index 9536bc8..77d5e41 100644
--- a/libs/hwui/PixelBuffer.h
+++ b/libs/hwui/PixelBuffer.h
@@ -18,7 +18,8 @@
 #define ANDROID_HWUI_PIXEL_BUFFER_H
 
 #include <GLES3/gl3.h>
-#include <cutils/log.h>
+
+#include <log/log.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 848161e..a766381 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -13,17 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #include "Properties.h"
-
 #include "Debug.h"
 
-#include <cutils/compiler.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
 #include <algorithm>
 #include <cstdlib>
 
+#include <log/log.h>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index c5156cf..f32612d 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -16,9 +16,11 @@
 
 #include "SkiaCanvasProxy.h"
 
-#include "hwui/Bitmap.h"
+#include <memory>
 
-#include <cutils/log.h>
+#include <log/log.h>
+
+#include "hwui/Bitmap.h"
 #include <SkLatticeIter.h>
 #include <SkPatchUtils.h>
 #include <SkPaint.h>
@@ -30,8 +32,6 @@
 #include <SkSurface.h>
 #include <SkTextBlobRunIterator.h>
 
-#include <memory>
-
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index f172473..956f66e 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -16,9 +16,10 @@
 
 #include "MinikinSkia.h"
 
+#include <log/log.h>
+
 #include <SkPaint.h>
 #include <SkTypeface.h>
-#include <cutils/log.h>
 
 namespace android {
 
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 8dd165c..713e509 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -13,15 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 #include "MinikinUtils.h"
 
+#include <string>
+
+#include <log/log.h>
+
 #include "Paint.h"
 #include "SkPathMeasure.h"
 #include "Typeface.h"
 
-#include <cutils/log.h>
-#include <string>
-
 namespace android {
 
 minikin::FontStyle MinikinUtils::prepareMinikinPaint(minikin::MinikinPaint* minikinPaint,
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
index 94818b2..c127478 100644
--- a/libs/hwui/utils/GLUtils.h
+++ b/libs/hwui/utils/GLUtils.h
@@ -18,7 +18,7 @@
 
 #include "Debug.h"
 
-#include <cutils/log.h>
+#include <log/log.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 0b22ad5..7c60467 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -15,7 +15,6 @@
  */
 
 #define LOG_TAG "PointerController"
-
 //#define LOG_NDEBUG 0
 
 // Log debug messages about pointer updates
@@ -23,8 +22,9 @@
 
 #include "PointerController.h"
 
-#include <cutils/log.h>
+#include <log/log.h>
 
+// ToDo: Fix code to be warning free
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #include <SkBitmap.h>
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 18ebd47..4991f04 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -15,15 +15,15 @@
  */
 
 #define LOG_TAG "Sprites"
-
 //#define LOG_NDEBUG 0
 
 #include "SpriteController.h"
 
-#include <cutils/log.h>
+#include <log/log.h>
 #include <utils/String8.h>
 #include <gui/Surface.h>
 
+// ToDo: Fix code to be warning free
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-parameter"
 #include <SkBitmap.h>
diff --git a/media/mca/filterpacks/native/base/geometry.cpp b/media/mca/filterpacks/native/base/geometry.cpp
index 7812d502..44b13e4 100644
--- a/media/mca/filterpacks/native/base/geometry.cpp
+++ b/media/mca/filterpacks/native/base/geometry.cpp
@@ -13,10 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "geometry"
 
-#include <cutils/log.h>
 #include <cmath>
 
+#include <log/log.h>
+
 #include "geometry.h"
 
 namespace android {
diff --git a/media/mca/filterpacks/native/base/time_util.cpp b/media/mca/filterpacks/native/base/time_util.cpp
index 1a78a95..7d383df 100644
--- a/media/mca/filterpacks/native/base/time_util.cpp
+++ b/media/mca/filterpacks/native/base/time_util.cpp
@@ -13,14 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "time_util"
 
 #include "time_util.h"
 #include "utilities.h"
 
-#include <cutils/log.h>
 #include <sys/time.h>
 #include <map>
 
+#include <log/log.h>
+
 namespace android {
 namespace filterfw {
 
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 4154ef0..329514c 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -542,16 +542,27 @@
     }
 
     /**
-     * This method is part of the SurfaceHolder.Callback interface, and is
+     * This method is part of the SurfaceHolder.Callback2 interface, and is
      * not normally called or subclassed by clients of GLSurfaceView.
      */
     @Override
-    public void surfaceRedrawNeeded(SurfaceHolder holder) {
+    public void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable finishDrawing) {
         if (mGLThread != null) {
-            mGLThread.requestRenderAndWait();
+            mGLThread.requestRenderAndNotify(finishDrawing);
         }
     }
 
+    /**
+     * This method is part of the SurfaceHolder.Callback2 interface, and is
+     * not normally called or subclassed by clients of GLSurfaceView.
+     */
+    @Deprecated
+    @Override
+    public void surfaceRedrawNeeded(SurfaceHolder holder) {
+        // Since we are part of the framework we know only surfaceRedrawNeededAsync
+        // will be called.
+    }
+
 
     /**
      * Pause the rendering thread, optionally tearing down the EGL context
@@ -1305,6 +1316,7 @@
                 int w = 0;
                 int h = 0;
                 Runnable event = null;
+                Runnable finishDrawingRunnable = null;
 
                 while (true) {
                     synchronized (sGLThreadManager) {
@@ -1400,6 +1412,11 @@
                                 sGLThreadManager.notifyAll();
                             }
 
+                            if (mFinishDrawingRunnable != null) {
+                                finishDrawingRunnable = mFinishDrawingRunnable;
+                                mFinishDrawingRunnable = null;
+                            }
+
                             // Ready to draw?
                             if (readyToDraw()) {
 
@@ -1453,7 +1470,6 @@
                                     break;
                                 }
                             }
-
                             // By design, this is the only place in a GLThread thread where we wait().
                             if (LOG_THREADS) {
                                 Log.i("GLThread", "waiting tid=" + getId()
@@ -1546,6 +1562,10 @@
                             try {
                                 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "onDrawFrame");
                                 view.mRenderer.onDrawFrame(gl);
+                                if (finishDrawingRunnable != null) {
+                                    finishDrawingRunnable.run();
+                                    finishDrawingRunnable = null;
+                                }
                             } finally {
                                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
                             }
@@ -1625,7 +1645,7 @@
             }
         }
 
-        public void requestRenderAndWait() {
+        public void requestRenderAndNotify(Runnable finishDrawing) {
             synchronized(sGLThreadManager) {
                 // If we are already on the GL thread, this means a client callback
                 // has caused reentrancy, for example via updating the SurfaceView parameters.
@@ -1638,17 +1658,9 @@
                 mWantRenderNotification = true;
                 mRequestRender = true;
                 mRenderComplete = false;
+                mFinishDrawingRunnable = finishDrawing;
 
                 sGLThreadManager.notifyAll();
-
-                while (!mExited && !mPaused && !mRenderComplete && ableToDraw()) {
-                    try {
-                        sGLThreadManager.wait();
-                    } catch (InterruptedException ex) {
-                        Thread.currentThread().interrupt();
-                    }
-                }
-
             }
         }
 
@@ -1821,6 +1833,7 @@
         private boolean mRenderComplete;
         private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
         private boolean mSizeChanged = true;
+        private Runnable mFinishDrawingRunnable = null;
 
         // End of member variables protected by the sGLThreadManager monitor.
 
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 8cf375a..cbd295e1 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -287,26 +287,23 @@
         String path = file.getAbsolutePath();
 
         // Find the most-specific root path
-        String mostSpecificId = null;
-        String mostSpecificPath = null;
-        synchronized (mRootsLock) {
-            for (int i = 0; i < mRoots.size(); i++) {
-                final String rootId = mRoots.keyAt(i);
-                final String rootPath = mRoots.valueAt(i).path.getAbsolutePath();
-                if (path.startsWith(rootPath) && (mostSpecificPath == null
-                        || rootPath.length() > mostSpecificPath.length())) {
-                    mostSpecificId = rootId;
-                    mostSpecificPath = rootPath;
-                }
-            }
+        boolean visiblePath = false;
+        RootInfo mostSpecificRoot = getMostSpecificRootForPath(path, false);
+
+        if (mostSpecificRoot == null) {
+            // Try visible path if no internal path matches. MediaStore uses visible paths.
+            visiblePath = true;
+            mostSpecificRoot = getMostSpecificRootForPath(path, true);
         }
 
-        if (mostSpecificPath == null) {
+        if (mostSpecificRoot == null) {
             throw new FileNotFoundException("Failed to find root that contains " + path);
         }
 
         // Start at first char of path under root
-        final String rootPath = mostSpecificPath;
+        final String rootPath = visiblePath
+                ? mostSpecificRoot.visiblePath.getAbsolutePath()
+                : mostSpecificRoot.path.getAbsolutePath();
         if (rootPath.equals(path)) {
             path = "";
         } else if (rootPath.endsWith("/")) {
@@ -322,7 +319,29 @@
             }
         }
 
-        return mostSpecificId + ':' + path;
+        return mostSpecificRoot.rootId + ':' + path;
+    }
+
+    private RootInfo getMostSpecificRootForPath(String path, boolean visible) {
+        // Find the most-specific root path
+        RootInfo mostSpecificRoot = null;
+        String mostSpecificPath = null;
+        synchronized (mRootsLock) {
+            for (int i = 0; i < mRoots.size(); i++) {
+                final RootInfo root = mRoots.valueAt(i);
+                final File rootFile = visible ? root.visiblePath : root.path;
+                if (rootFile != null) {
+                    final String rootPath = rootFile.getAbsolutePath();
+                    if (path.startsWith(rootPath) && (mostSpecificPath == null
+                            || rootPath.length() > mostSpecificPath.length())) {
+                        mostSpecificRoot = root;
+                        mostSpecificPath = rootPath;
+                    }
+                }
+            }
+        }
+
+        return mostSpecificRoot;
     }
 
     private File getFileForDocId(String docId) throws FileNotFoundException {
@@ -519,15 +538,13 @@
                 boolean matchesRequestedDoc = false;
                 if (DocumentsContract.isTreeUri(uri)) {
                     final String parentDocId = DocumentsContract.getTreeDocumentId(uri);
-                    File parentFile = getFileForDocId(parentDocId);
-                    if (FileUtils.contains(parentFile, doc)) {
+                    if (isChildDocument(parentDocId, docId)) {
                         treeUriPermission = uriPermission;
                         matchesRequestedDoc = true;
                     }
                 } else {
                     final String candidateDocId = DocumentsContract.getDocumentId(uri);
-                    final File candidateDoc = getFileForDocId(candidateDocId);
-                    if (Objects.equals(doc.getAbsolutePath(), candidateDoc.getAbsolutePath())) {
+                    if (Objects.equals(docId, candidateDocId)) {
                         docUriPermission = uriPermission;
                         matchesRequestedDoc = true;
                     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
index de76279..320494c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -41,4 +41,9 @@
     public List<VolumeInfo> getVolumes() {
         return mStorageManager.getVolumes();
     }
+
+    @Override
+    public VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume) {
+        return mStorageManager.findEmulatedForPrivate(privateVolume);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
index 95bb18d..646c42f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -34,4 +34,9 @@
      * Returns a list of VolumeInfos for the device.
      */
     List<VolumeInfo> getVolumes();
+
+    /**
+     * Returns the emulated volume for a given private volume.
+     */
+    VolumeInfo findEmulatedForPrivate(VolumeInfo privateVolume);
 }
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..c3aea46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..470b3e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
index 94cb032..965d2f5 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..e7137c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..03dec15
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..e1ca853
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..0520c49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..3dc2b88
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..2ba5d5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..62dc2d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..e718b7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..469800a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..42863c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..d9ec9d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked.png
new file mode 100644
index 0000000..ea7ac93
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..8ee4e43
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..dfa8a97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..d23abc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..8e56e9c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..28a1465
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..0fc9677
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..7b81eee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..a6483452
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..7f74521
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
index fbdc93c..3b831a3 100644
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..8c99455
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
index 419518c..3c37782 100644
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked.png
new file mode 100644
index 0000000..b2baa09
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..b78dc9c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
index a2406b1..37590a5 100644
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..3a208aa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..625ba45
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
index c449449..7ad2a29 100644
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..604397e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..274e5df
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..ac16895
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..e69a037
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_ime_dark.png
new file mode 100644
index 0000000..65a4354
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..8bddcd9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..38c5959
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
new file mode 100644
index 0000000..c6d7c98
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime_dark.png
new file mode 100644
index 0000000..06c52aa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked_dark.png
new file mode 100644
index 0000000..7660997
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home_dark.png
new file mode 100644
index 0000000..0d9ecc2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu_dark.png
new file mode 100644
index 0000000..d6bb8b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent_dark.png
new file mode 100644
index 0000000..298ef3a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index ca0248e..04d0e65 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -27,7 +27,7 @@
 
     <android.support.v7.widget.RecyclerView
         android:id="@android:id/list"
-        android:layout_width="@dimen/notification_panel_width"
+        android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:scrollIndicators="top"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index d86aebf..416c7ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -47,13 +47,11 @@
     public FlashlightTile(Host host) {
         super(host);
         mFlashlightController = host.getFlashlightController();
-        mFlashlightController.addCallback(this);
     }
 
     @Override
     protected void handleDestroy() {
         super.handleDestroy();
-        mFlashlightController.removeCallback(this);
     }
 
     @Override
@@ -63,6 +61,11 @@
 
     @Override
     public void setListening(boolean listening) {
+        if (listening) {
+            mFlashlightController.addCallback(this);
+        } else {
+            mFlashlightController.removeCallback(this);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index e8039c3..3059a05 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -30,6 +30,9 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.util.Log;
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
@@ -52,9 +55,12 @@
     private static final int MSG_SET_CHECKED = 2;
     private static final int MSG_ATTACH_LISTENER = 3;
     private static final int MSG_DETACH_LISTENER = 4;
+    private static final int MSG_VR_MODE_CHANGED = 5;
 
     private final int mMinimumBacklight;
     private final int mMaximumBacklight;
+    private final int mMinimumBacklightForVr;
+    private final int mMaximumBacklightForVr;
 
     private final Context mContext;
     private final ImageView mIcon;
@@ -62,6 +68,7 @@
     private final boolean mAutomaticAvailable;
     private final IPowerManager mPower;
     private final CurrentUserTracker mUserTracker;
+    private final IVrManager mVrManager;
 
     private Handler mBackgroundHandler;
     private final BrightnessObserver mBrightnessObserver;
@@ -69,7 +76,8 @@
     private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
             new ArrayList<BrightnessStateChangeCallback>();
 
-    private volatile boolean mAutomatic;
+    private volatile boolean mAutomatic;  // Brightness adjusted automatically using ambient light.
+    private volatile boolean mIsVrModeEnabled;
     private boolean mListening;
     private boolean mExternalChange;
 
@@ -84,6 +92,8 @@
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);
         private final Uri BRIGHTNESS_URI =
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
+        private final Uri BRIGHTNESS_FOR_VR_URI =
+                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR);
         private final Uri BRIGHTNESS_ADJ_URI =
                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);
 
@@ -105,6 +115,8 @@
                 mBackgroundHandler.post(mUpdateSliderRunnable);
             } else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
+            } else if (BRIGHTNESS_FOR_VR_URI.equals(uri)) {
+                mBackgroundHandler.post(mUpdateSliderRunnable);
             } else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {
                 mBackgroundHandler.post(mUpdateSliderRunnable);
             } else {
@@ -126,6 +138,9 @@
                     BRIGHTNESS_URI,
                     false, this, UserHandle.USER_ALL);
             cr.registerContentObserver(
+                    BRIGHTNESS_FOR_VR_URI,
+                    false, this, UserHandle.USER_ALL);
+            cr.registerContentObserver(
                     BRIGHTNESS_ADJ_URI,
                     false, this, UserHandle.USER_ALL);
         }
@@ -191,7 +206,14 @@
     private final Runnable mUpdateSliderRunnable = new Runnable() {
         @Override
         public void run() {
-            if (mAutomatic) {
+            if (mIsVrModeEnabled) {
+                int value = Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mMaximumBacklight,
+                        UserHandle.USER_CURRENT);
+                mHandler.obtainMessage(MSG_UPDATE_SLIDER,
+                        mMaximumBacklightForVr - mMinimumBacklightForVr,
+                        value - mMinimumBacklightForVr).sendToTarget();
+            } else if (mAutomatic) {
                 float value = Settings.System.getFloatForUser(mContext.getContentResolver(),
                         Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0,
                         UserHandle.USER_CURRENT);
@@ -208,6 +230,14 @@
         }
     };
 
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+        @Override
+        public void onVrStateChanged(boolean enabled) {
+            mHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
+                    .sendToTarget();
+        }
+    };
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -230,6 +260,9 @@
                     case MSG_DETACH_LISTENER:
                         mControl.setOnChangedListener(null);
                         break;
+                    case MSG_VR_MODE_CHANGED:
+                        updateVrMode(msg.arg1 != 0);
+                        break;
                     default:
                         super.handleMessage(msg);
                 }
@@ -256,10 +289,13 @@
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
         mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
+        mMinimumBacklightForVr = pm.getMinimumScreenBrightnessForVrSetting();
+        mMaximumBacklightForVr = pm.getMaximumScreenBrightnessForVrSetting();
 
         mAutomaticAvailable = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_automatic_brightness_available);
         mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
+        mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
     }
 
     public void setBackgroundLooper(Looper backgroundLooper) {
@@ -284,6 +320,15 @@
             return;
         }
 
+        if (mVrManager != null) {
+            try {
+                mVrManager.registerListener(mVrStateCallbacks);
+                mIsVrModeEnabled = mVrManager.getVrModeState();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to register VR mode state listener: ", e);
+            }
+        }
+
         mBackgroundHandler.post(mStartListeningRunnable);
         mListening = true;
     }
@@ -294,6 +339,14 @@
             return;
         }
 
+        if (mVrManager != null) {
+            try {
+                mVrManager.unregisterListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to unregister VR mode state listener: ", e);
+            }
+        }
+
         mBackgroundHandler.post(mStopListeningRunnable);
         mListening = false;
     }
@@ -304,7 +357,22 @@
         updateIcon(mAutomatic);
         if (mExternalChange) return;
 
-        if (!mAutomatic) {
+        if (mIsVrModeEnabled) {
+            final int val = value + mMinimumBacklightForVr;
+            if (stopTracking) {
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_FOR_VR, val);
+            }
+            setBrightness(val);
+            if (!tracking) {
+                AsyncTask.execute(new Runnable() {
+                        public void run() {
+                            Settings.System.putIntForUser(mContext.getContentResolver(),
+                                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR, val,
+                                    UserHandle.USER_CURRENT);
+                        }
+                    });
+            }
+        } else if (!mAutomatic) {
             final int val = value + mMinimumBacklight;
             if (stopTracking) {
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
@@ -368,4 +436,11 @@
                     com.android.systemui.R.drawable.ic_qs_brightness_auto_off);
         }
     }
+
+    private void updateVrMode(boolean isEnabled) {
+        if (mIsVrModeEnabled != isEnabled) {
+            mIsVrModeEnabled = isEnabled;
+            mBackgroundHandler.post(mUpdateSliderRunnable);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index 008d837..f0cfa2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -121,6 +121,8 @@
             }
             cleanUpListenersLocked(l);
             mListeners.add(new WeakReference<>(l));
+            l.onFlashlightAvailabilityChanged(mTorchAvailable);
+            l.onFlashlightChanged(mFlashlightEnabled);
         }
     }
 
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index cf372bc..b5afc40 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -17,14 +17,26 @@
   optional int32 network_id = 1;
 };
 
-// Transport describes a physical technology used by a network. It is a subset
-// of the TRANSPORT_* constants defined in android.net.NetworkCapabilities.
-enum Transport {
+// LinkLayer describes a physical link layer technology used by a network.
+// It is not intended to map one to one to the TRANSPORT_* constants defined in
+// android.net.NetworkCapabilities. Instead it is intended to be used as
+// a dimension field for metrics events and aggregated metrics.
+// Next tag: 7
+enum LinkLayer {
+  // An unknown link layer technology.
   UNKNOWN   = 0;
+
   BLUETOOTH = 1;
   CELLULAR  = 2;
   ETHERNET  = 3;
   WIFI      = 4;
+
+  // Indicates that the link layer dimension is not relevant for the metrics or
+  // event considered.
+  NONE      = 5;
+
+  // Indicates that the metrics or event considered may involve several links.
+  MULTIPLE  = 6;
 };
 
 // A pair of (key, value) integers for describing histogram-like statistics.
@@ -65,7 +77,7 @@
 // This message is associated to android.net.metrics.IpReachabilityEvent.
 message IpReachabilityEvent {
   // The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
-  // Deprecated since version 2, replaced by transport field.
+  // Deprecated since version 2, to be replaced by link_layer field.
   optional string if_name = 1 [deprecated = true];
 
   // The event type code of the probe, represented by constants defined in
@@ -179,7 +191,7 @@
 // android.net.metrics.DhcpErrorEvent.
 message DHCPEvent {
   // The interface name (wlan, rmnet, lo, ...) on which the event happened.
-  // Deprecated since version 2, replaced by transport field.
+  // Deprecated since version 2, to be replaced by link_layer field.
   optional string if_name = 1 [deprecated = true];
 
   oneof value {
@@ -284,7 +296,7 @@
 // This message is associated to android.net.metrics.IpManagerEvent.
 message IpProvisioningEvent {
   // The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
-  // Deprecated since version 2, replaced by transport field.
+  // Deprecated since version 2, to be replaced by link_layer field.
   optional string if_name = 1 [deprecated = true];
 
   // The code of the IP provisioning event, represented by constants defined in
@@ -296,19 +308,21 @@
 }
 
 // Represents one of the IP connectivity event defined in this file.
-// Next tag: 15
+// Next tag: 16
 message IpConnectivityEvent {
   // Time in ms when the event was recorded.
   optional int64 time_ms = 1;
 
-  // Physical transport of the network on which the event happened.
+  // Physical link layer of the network on which the event happened.
+  // Acts as a dimension key.
   // Since version 2.
-  optional Transport transport = 12;
+  optional LinkLayer link_layer = 15;
 
   // Event type.
   oneof event {
 
     // An event about the system default network.
+    // The link_layer field is not relevant for this event and set to NONE.
     DefaultNetworkEvent default_network_event = 2;
 
     // An IP reachability probe event.
@@ -318,7 +332,8 @@
     NetworkEvent network_event = 4;
 
     // A batch of DNS lookups.
-    // Deprecated in the nyc-mr2 release since version 2, and replaced by dns_latencies.
+    // Deprecated in the nyc-mr2 release since version 2,and replaced by
+    // dns_latencies.
     DNSLookupBatch dns_lookup_batch = 5 [deprecated = true];
 
     // DNS lookup latency statistics.
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 57c4565..bf3620e 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3105,6 +3105,12 @@
     // PACKAGE: The package name of the app the permission was revoked for
     ACTION_PERMISSION_REVOKE_READ_PHONE_NUMBER = 739;
 
+    // ACTION: QS Brightness Slider (with auto brightness disabled, and VR enabled)
+    //   SUBTYPE: slider value
+    // CATEGORY: QUICK_SETTINGS
+    // OS: 6.0
+    ACTION_BRIGHTNESS_FOR_VR = 498;
+
     // ACTION: A captive portal was detected during network validation
     // CATEGORY: NOTIFICATION
     // OS: N-MR2
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 6a16131..87eaf29 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -18,28 +18,23 @@
 
 import static android.Manifest.permission.MANAGE_AUTO_FILL;
 import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
-import static android.view.View.ASSIST_FLAG_SANITIZED_TEXT;
-import static android.view.View.ASSIST_FLAG_NON_SANITIZED_TEXT;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_FILL;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_SAVE;
+
+import static com.android.server.autofill.AutoFillUI.MSG_SHOW_ALL_NOTIFICATIONS;
+import static com.android.server.autofill.AutoFillUI.SHOW_ALL_NOTIFICATIONS_DELAY_MS;
 
 import android.Manifest;
 import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.Notification.Action;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -48,7 +43,6 @@
 import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.service.autofill.IAutoFillManagerService;
 import android.text.TextUtils;
@@ -65,7 +59,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.List;
 
 /**
  * Entry point service for auto-fill management.
@@ -86,6 +79,7 @@
     protected static final int MSG_UNBIND = 1;
 
     private final AutoFillManagerServiceStub mServiceStub;
+    private final AutoFillUI mUi;
     private final Context mContext;
     private final ContentResolver mResolver;
 
@@ -99,7 +93,7 @@
                     removeStaleServiceForUser(msg.arg1);
                     return;
                 case MSG_SHOW_ALL_NOTIFICATIONS:
-                    showAllNotifications();
+                    mUi.showAllNotifications();
                     return;
                 default:
                     Slog.w(TAG, "Invalid message: " + msg);
@@ -129,6 +123,7 @@
         super(context);
 
         mContext = context;
+        mUi = new AutoFillUI(context, this, mLock);
         mResolver = context.getContentResolver();
         mServiceStub = new AutoFillManagerServiceStub();
     }
@@ -176,8 +171,9 @@
             Slog.w(TAG, "no service info for " + serviceComponent);
             return null;
         }
-        return new AutoFillManagerServiceImpl(this, mContext, mLock, FgThread.getHandler(), userId,
-                serviceInfo.applicationInfo.uid, serviceComponent, SERVICE_BINDING_LIFETIME_MS);
+        return new AutoFillManagerServiceImpl(this, mUi, mContext, mLock, FgThread.getHandler(),
+                userId, serviceInfo.applicationInfo.uid, serviceComponent,
+                SERVICE_BINDING_LIFETIME_MS);
     }
 
     /**
@@ -186,7 +182,8 @@
      * <p>First it tries to return the existing instance from the cache; if it's not cached, it
      * creates a new instance and caches it.
      */
-    private AutoFillManagerServiceImpl getServiceForUserLocked(int userId) {
+    // TODO(b/33197203): make private once AutoFillUi does not uses notifications
+    AutoFillManagerServiceImpl getServiceForUserLocked(int userId) {
         AutoFillManagerServiceImpl service = mServicesCache.get(userId);
         if (service != null) {
             if (DEBUG) Log.d(TAG, "reusing cached service for userId " + userId);
@@ -251,14 +248,14 @@
     final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
 
         @Override
-        public void requestAutoFill(IBinder activityToken, int userId, int flags) {
+        public void requestAutoFill(IBinder activityToken, int userId, Bundle extras, int flags) {
             if (DEBUG) Slog.d(TAG, "requestAutoFill: flags=" + flags + ", userId=" + userId);
             mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
 
             synchronized (mLock) {
                 final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
                 if (service != null) {
-                    service.requestAutoFill(activityToken, flags);
+                    service.requestAutoFill(activityToken, extras, flags);
                 }
             }
         }
@@ -310,147 +307,8 @@
             if (DEBUG) Slog.d(TAG, "settings (" + uri + " changed for " + userId);
             synchronized (mLock) {
                 removeCachedServiceForUserLocked(userId);
-                final ComponentName serviceComponent = getProviderForUser(userId);
-                if (serviceComponent == null) {
-                    cancelNotificationLocked(userId);
-                } else {
-                    showNotification(serviceComponent, userId);
-                }
+                mUi.updateNotification(userId);
             }
         }
     }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // TODO: temporary code using a notification to request auto-fill.        //
-    // Will be removed once UX decide the right way to present it to the user //
-    ////////////////////////////////////////////////////////////////////////////
-
-    // TODO: remove from frameworks/base/core/res/AndroidManifest.xml once it's not used anymore
-    private static final String NOTIFICATION_AUTO_FILL_INTENT =
-            "com.android.internal.autofill.action.REQUEST_AUTOFILL";
-    private static final String EXTRA_USER_ID = "user_id";
-    private static final String EXTRA_FLAGS = "flags";
-
-    private static final int MSG_SHOW_ALL_NOTIFICATIONS = 42;
-    private static final int SHOW_ALL_NOTIFICATIONS_DELAY_MS = 5000;
-
-    private BroadcastReceiver mNotificationReceiver;
-
-    final class NotificationReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final int userId = intent.getIntExtra(EXTRA_USER_ID, -1);
-            final int flags = intent.getIntExtra(EXTRA_FLAGS, 0);
-            if (DEBUG) Slog.d(TAG, "Requesting autofill by notification for user " + userId);
-            synchronized (mLock) {
-                final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-                if (service == null) {
-                    Slog.w(TAG, "no auto-fill service for user " + userId);
-                } else {
-                    service.requestAutoFill(null, flags);
-                }
-            }
-        }
-    }
-
-    private ComponentName getProviderForUser(int userId) {
-        ComponentName serviceComponent = null;
-        ServiceInfo serviceInfo = null;
-        final String componentName = Settings.Secure.getStringForUser(
-                mResolver, Settings.Secure.AUTO_FILL_SERVICE, userId);
-        if (!TextUtils.isEmpty(componentName)) {
-            try {
-                serviceComponent = ComponentName.unflattenFromString(componentName);
-                serviceInfo =
-                        AppGlobals.getPackageManager().getServiceInfo(serviceComponent, 0, userId);
-            } catch (RuntimeException | RemoteException e) {
-                Slog.wtf(TAG, "Bad auto-fill service name " + componentName, e);
-                return null;
-            }
-        }
-
-        if (DEBUG) Slog.d(TAG, "getServiceComponentForUser(" + userId + "): component="
-                + serviceComponent + ", info: " + serviceInfo);
-        if (serviceInfo == null) {
-            Slog.w(TAG, "no service info for " + serviceComponent);
-            return null;
-        }
-        return serviceComponent;
-    }
-
-    private void showAllNotifications() {
-        final UserManager userManager =
-                (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-
-        final List<UserInfo> allUsers = userManager.getUsers(true);
-
-        for (UserInfo user : allUsers) {
-            final ComponentName serviceComponent = getProviderForUser(user.id);
-            if (serviceComponent != null) {
-                showNotification(serviceComponent, user.id);
-            }
-        }
-    }
-
-    private void showNotification(ComponentName serviceComponent, int userId) {
-        if (DEBUG) Log.d(TAG, "showNotification() for " + userId + ": " + serviceComponent);
-
-        synchronized (mLock) {
-            if (mNotificationReceiver == null) {
-                mNotificationReceiver = new NotificationReceiver();
-                mContext.registerReceiver(mNotificationReceiver,
-                        new IntentFilter(NOTIFICATION_AUTO_FILL_INTENT));
-            }
-        }
-
-        final Intent fillIntent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
-        fillIntent.putExtra(EXTRA_USER_ID, userId);
-        fillIntent.putExtra(EXTRA_FLAGS, ASSIST_FLAG_SANITIZED_TEXT);
-        final PendingIntent fillPendingIntent = PendingIntent.getBroadcast(mContext,
-                ASSIST_FLAG_SANITIZED_TEXT, fillIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-        final Action fillAction = new Action.Builder(null, "FILL", fillPendingIntent).build();
-
-        final Intent saveIntent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
-        saveIntent.putExtra(EXTRA_USER_ID, userId);
-        saveIntent.putExtra(EXTRA_FLAGS, ASSIST_FLAG_NON_SANITIZED_TEXT);
-        final PendingIntent savePendingIntent = PendingIntent.getBroadcast(mContext,
-                ASSIST_FLAG_NON_SANITIZED_TEXT, saveIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-        final Action saveAction = new Action.Builder(null, "SAVE", savePendingIntent).build();
-
-        final String packageName = serviceComponent.getPackageName();
-        String providerName = null;
-        final PackageManager pm = mContext.getPackageManager();
-        try {
-            final ApplicationInfo info = pm.getApplicationInfoAsUser(packageName, 0, userId);
-            if (info != null) {
-                providerName = pm.getApplicationLabel(info).toString();
-            }
-        } catch (Exception e) {
-            providerName = packageName;
-        }
-        final String title = "AutoFill actions";
-        final String subTitle = "Provider: " + providerName + "\n" + "User: " + userId;
-
-        final Notification notification = new Notification.Builder(mContext)
-                .setCategory(Notification.CATEGORY_SYSTEM)
-                .setOngoing(true)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setLocalOnly(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
-                .setContentTitle(title)
-                .setStyle(new Notification.BigTextStyle().bigText(subTitle))
-                .setActions(fillAction, saveAction)
-                .build();
-        NotificationManager.from(mContext).notify(userId, notification);
-    }
-
-    private void cancelNotificationLocked(int userId) {
-        if (DEBUG) Log.d(TAG, "cancelNotificationLocked(): " + userId);
-        NotificationManager.from(mContext).cancel(userId);
-    }
-
-    /////////////////////////////////////////
-    // End of temporary notification code. //
-    /////////////////////////////////////////
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 82356c8..3de8a8b 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -18,9 +18,12 @@
 
 import static com.android.server.autofill.AutoFillManagerService.DEBUG;
 
+import android.annotation.Nullable;
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.IActivityManager;
+import android.app.assist.AssistStructure;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +32,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.icu.text.DateFormat;
+import android.os.Bundle;
 import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
@@ -37,16 +41,24 @@
 import android.os.UserHandle;
 import android.service.autofill.AutoFillService;
 import android.service.autofill.AutoFillServiceInfo;
+import android.service.autofill.IAutoFillAppCallback;
+import android.service.autofill.IAutoFillServerCallback;
 import android.service.autofill.IAutoFillService;
-import android.util.Log;
+import android.service.voice.VoiceInteractionSession;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.TimeUtils;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.Dataset;
+import android.view.autofill.FillResponse;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.IResultReceiver;
 import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -60,6 +72,9 @@
 
     private static final String TAG = "AutoFillManagerServiceImpl";
 
+    /** Used do assign ids to new ServerCallback instances. */
+    private static int sServerCallbackCounter = 0;
+
     private final int mUserId;
     private final int mUid;
     private final ComponentName mComponent;
@@ -68,6 +83,7 @@
     private final Object mLock;
     private final AutoFillServiceInfo mInfo;
     private final AutoFillManagerService mManagerService;
+    private final AutoFillUI mUi;
 
     // TODO(b/33197203): improve its usage
     // - set maximum number of entries
@@ -89,10 +105,19 @@
         }
     };
 
+    /**
+     * Cache of pending ServerCallbacks, keyed by {@link ServerCallback#id}.
+     *
+     * <p>They're kept until the AutoFillService handles a request, or an error occurs.
+     */
+    // TODO(b/33197203): need to make sure service is bound while callback is pending
+    @GuardedBy("mLock")
+    private static final SparseArray<ServerCallback> mServerCallbacks = new SparseArray<>();
+
     private final ServiceConnection mConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            if (DEBUG) Log.d(TAG, "onServiceConnected():" + name);
+            if (DEBUG) Slog.d(TAG, "onServiceConnected():" + name);
             synchronized (mLock) {
                 mService = IAutoFillService.Stub.asInterface(service);
                 try {
@@ -102,17 +127,18 @@
                     return;
                 }
                 if (!mQueuedRequests.isEmpty()) {
-                    if (DEBUG) Log.d(TAG, "queued requests:" + mQueuedRequests.size());
+                    if (DEBUG) Slog.d(TAG, "queued requests:" + mQueuedRequests.size());
                 }
                 for (final QueuedRequest request: mQueuedRequests) {
-                    requestAutoFillLocked(request.activityToken, request.flags, false);
+                    requestAutoFillLocked(request.activityToken, request.extras, request.flags,
+                            false);
                 }
             }
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
-            if (DEBUG) Log.d(TAG, name + " disconnected");
+            if (DEBUG) Slog.d(TAG, name + " disconnected");
             synchronized (mLock) {
                 mService = null;
                 mManagerService.removeCachedServiceForUserLocked(mUserId);
@@ -120,6 +146,39 @@
         }
     };
 
+
+    /**
+     * Receiver of assist data from the app's {@link Activity}, uses the {@code resultData} as
+     * the {@link ServerCallback#id}.
+     */
+    private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
+        @Override
+        public void send(int resultCode, Bundle resultData) throws RemoteException {
+            if (DEBUG) Slog.d(TAG, "resultCode on mAssistReceiver: " + resultCode);
+
+            final IBinder appBinder = resultData.getBinder(AutoFillService.KEY_CALLBACK);
+            if (appBinder == null) {
+                Slog.w(TAG, "no app callback on mAssistReceiver's resultData");
+                return;
+            }
+            final AssistStructure structure = resultData
+                    .getParcelable(VoiceInteractionSession.KEY_STRUCTURE);
+            final Bundle data = resultData.getBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS);
+            final int flags = resultData.getInt(VoiceInteractionSession.KEY_FLAGS, 0);
+
+            final ServerCallback serverCallback;
+            synchronized (mLock) {
+                serverCallback = mServerCallbacks.get(resultCode);
+                if (serverCallback == null) {
+                    Slog.w(TAG, "no server callback for id " + resultCode);
+                    return;
+                }
+                serverCallback.appCallback = IAutoFillAppCallback.Stub.asInterface(appBinder);
+            }
+            mService.autoFill(structure, serverCallback, serverCallback.extras, flags);
+        }
+    };
+
     @GuardedBy("mLock")
     private IAutoFillService mService;
     private boolean mBound;
@@ -128,9 +187,11 @@
     // Estimated time when the service will be evicted from the cache.
     long mEstimateTimeOfDeath;
 
-    AutoFillManagerServiceImpl(AutoFillManagerService managerService, Context context, Object lock,
-            Handler handler, int userId, int uid,ComponentName component, long ttl) {
+    AutoFillManagerServiceImpl(AutoFillManagerService managerService, AutoFillUI ui,
+            Context context, Object lock, Handler handler, int userId, int uid,
+            ComponentName component, long ttl) {
         mManagerService = managerService;
+        mUi = ui;
         mContext = context;
         mLock = lock;
         mUserId = userId;
@@ -180,7 +241,14 @@
         if (DEBUG) Slog.d(TAG, "Bound to " + mComponent);
     }
 
-    void requestAutoFill(IBinder activityToken, int flags) {
+    /**
+     * Asks service to auto-fill an activity.
+     *
+     * @param activityToken activity token
+     * @param extras bundle to be passed to the {@link AutoFillService} method.
+     * @param flags optional flags.
+     */
+    void requestAutoFill(@Nullable IBinder activityToken, @Nullable Bundle extras, int flags) {
         synchronized (mLock) {
             if (!mBound) {
                 Slog.w(TAG, "requestAutoFill() failed because it's not bound to service");
@@ -211,21 +279,26 @@
                 DateFormat.getDateTimeInstance().format(new Date()) + " - " + activityToken;
         synchronized (mLock) {
             mRequestHistory.add(historyItem);
-            requestAutoFillLocked(activityToken, flags, true);
+            requestAutoFillLocked(activityToken, extras, flags, true);
         }
     }
 
-    private void requestAutoFillLocked(IBinder activityToken, int flags, boolean queueIfNecessary) {
+    private void requestAutoFillLocked(IBinder activityToken, @Nullable Bundle extras, int flags,
+            boolean queueIfNecessary) {
         if (mService == null) {
             if (!queueIfNecessary) {
                 Slog.w(TAG, "requestAutoFillLocked(): service is null");
                 return;
             }
             if (DEBUG) Slog.d(TAG, "requestAutoFill(): service not set yet, queuing it");
-            mQueuedRequests.add(new QueuedRequest(activityToken, flags));
+            mQueuedRequests.add(new QueuedRequest(activityToken, extras, flags));
             return;
         }
 
+        final int callbackId = ++sServerCallbackCounter;
+        final ServerCallback serverCallback = new ServerCallback(callbackId, extras);
+        mServerCallbacks.put(callbackId, serverCallback);
+
         /*
          * TODO(b/33197203): apply security checks below:
          * - checks if disabled by secure settings / device policy
@@ -235,8 +308,7 @@
          */
         try {
             // TODO(b/33197203): add MetricsLogger call
-            if (!mAm.requestAutoFillData(mService.getAssistReceiver(), null, activityToken,
-                    flags)) {
+            if (!mAm.requestAutoFillData(mAssistReceiver, null, callbackId, activityToken, flags)) {
                 // TODO(b/33197203): might need a way to warn user (perhaps a new method on
                 // AutoFillService).
                 Slog.w(TAG, "failed to request auto-fill data for " + activityToken);
@@ -251,7 +323,7 @@
 
         // Sanity check.
         if (mService == null) {
-            Log.w(TAG, "service already null on shutdown");
+            Slog.w(TAG, "service already null on shutdown");
             return;
         }
         try {
@@ -273,6 +345,44 @@
         }
     }
 
+    /**
+     * Called by {@link AutoFillUI} to fill an activity after the user selected a dataset.
+     */
+    void autoFillApp(int callbackId, Dataset dataset) {
+        // TODO(b/33197203): add MetricsLogger call
+
+        if (dataset == null) {
+            Slog.w(TAG, "autoFillApp(): no dataset for callback id " + callbackId);
+            return;
+        }
+
+        final ServerCallback serverCallback;
+        synchronized (mLock) {
+            serverCallback = mServerCallbacks.get(callbackId);
+            if (serverCallback == null) {
+                Slog.w(TAG, "autoFillApp(): no server callback with id " + callbackId);
+                return;
+            }
+            if (serverCallback.appCallback == null) {
+                Slog.w(TAG, "autoFillApp(): no app callback for server callback " + callbackId);
+                return;
+            }
+            // TODO(b/33197203): use a handler?
+            try {
+                if (DEBUG) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
+                serverCallback.appCallback.autoFill(dataset);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error auto-filling activity: " + e);
+            }
+            removeServerCallbackLocked(callbackId);
+        }
+    }
+
+    void removeServerCallbackLocked(int id) {
+        if (DEBUG) Slog.d(TAG, "Removing " + id + " from server callbacks");
+        mServerCallbacks.remove(id);
+    }
+
     void dumpLocked(String prefix, PrintWriter pw) {
         if (!mValid) {
             pw.print("  NOT VALID: ");
@@ -284,6 +394,8 @@
             return;
         }
 
+        final String prefix2 = prefix + "  ";
+
         pw.print(prefix); pw.print("mUserId="); pw.println(mUserId);
         pw.print(prefix); pw.print("mUid="); pw.println(mUid);
         pw.print(prefix); pw.print("mComponent="); pw.println(mComponent.flattenToShortString());
@@ -303,7 +415,6 @@
             pw.print(prefix); pw.println("No history");
         } else {
             pw.print(prefix); pw.println("History:");
-            final String prefix2 = prefix + prefix;
             for (int i = 0; i < mRequestHistory.size(); i++) {
                 pw.print(prefix2); pw.print(i); pw.print(": "); pw.println(mRequestHistory.get(i));
             }
@@ -312,11 +423,28 @@
             pw.print(prefix); pw.println("No queued requests");
         } else {
             pw.print(prefix); pw.println("Queued requests:");
-            final String prefix2 = prefix + prefix;
             for (int i = 0; i < mQueuedRequests.size(); i++) {
                 pw.print(prefix2); pw.print(i); pw.print(": "); pw.println(mQueuedRequests.get(i));
             }
         }
+
+        pw.print(prefix); pw.print("sServerCallbackCounter="); pw.println(sServerCallbackCounter);
+        final int size = mServerCallbacks.size();
+        if (size == 0) {
+            pw.print(prefix); pw.println("No server callbacks");
+        } else {
+            pw.print(prefix); pw.print(size); pw.println(" server callbacks:");
+            for (int i = 0; i < size; i++) {
+                pw.print(prefix2); pw.print(mServerCallbacks.keyAt(i));
+                final ServerCallback callback = mServerCallbacks.valueAt(i);
+                if (callback.appCallback == null) {
+                    pw.println("(no appCallback)");
+                } else {
+                    pw.print(" (app callback: "); pw.print(callback.appCallback) ; pw.println(")");
+                }
+            }
+            pw.println();
+        }
     }
 
     @Override
@@ -327,10 +455,12 @@
 
     private static final class QueuedRequest {
         final IBinder activityToken;
+        final Bundle extras;
         final int flags;
 
-        QueuedRequest(IBinder activityToken, int flags) {
+        QueuedRequest(IBinder activityToken, Bundle extras, int flags) {
             this.activityToken = activityToken;
+            this.extras = extras;
             this.flags = flags;
         }
 
@@ -339,4 +469,54 @@
             return "flags: " + flags + " token: " + activityToken;
         }
     }
+
+    /**
+     * A bridge between the {@link AutoFillService} implementation and the activity being
+     * auto-filled (represented through the {@link IAutoFillAppCallback}).
+     */
+    private final class ServerCallback extends IAutoFillServerCallback.Stub {
+
+        private final int id;
+        private final Bundle extras;
+        private IAutoFillAppCallback appCallback;
+
+        private ServerCallback(int id, Bundle extras) {
+            this.id = id;
+            this.extras = extras;
+        }
+
+        @Override
+        public void showResponse(FillResponse response) {
+            // TODO(b/33197203): add MetricsLogger call
+            if (DEBUG) Slog.d(TAG, "showResponse(): " + response);
+
+            mUi.showOptions(mUserId, id, response);
+        }
+
+        @Override
+        public void showError(String message) {
+            // TODO(b/33197203): add MetricsLogger call
+            if (DEBUG) Slog.d(TAG, "showError(): " + message);
+
+            mUi.showError(message);
+
+            removeSelf();
+        }
+
+        @Override
+        public void highlightSavedFields(AutoFillId[] ids) {
+            // TODO(b/33197203): add MetricsLogger call
+            if (DEBUG) Slog.d(TAG, "showSaved(): " + Arrays.toString(ids));
+
+            mUi.highlightSavedFields(ids);
+
+            removeSelf();
+        }
+
+        private void removeSelf() {
+            synchronized (mLock) {
+                removeServerCallbackLocked(id);
+            }
+        }
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index aa3503b..26f2451 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -16,10 +16,11 @@
 
 package com.android.server.autofill;
 
-import static android.view.View.ASSIST_FLAG_SANITIZED_TEXT;
-import static android.view.View.ASSIST_FLAG_NON_SANITIZED_TEXT;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_FILL;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_SAVE;
 
 import android.app.ActivityManager;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.os.UserHandle;
@@ -44,9 +45,9 @@
         try {
             switch (cmd) {
                 case "fill":
-                    return requestAutoFill(ASSIST_FLAG_SANITIZED_TEXT);
+                    return requestAutoFill(AUTO_FILL_FLAG_TYPE_FILL);
                 case "save":
-                    return requestAutoFill(ASSIST_FLAG_NON_SANITIZED_TEXT);
+                    return requestAutoFill(AUTO_FILL_FLAG_TYPE_SAVE);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -73,7 +74,7 @@
 
     private int requestAutoFill(int flags) throws RemoteException {
         final int userId = getUserIdFromArgs();
-        mService.requestAutoFill(null, userId, flags);
+        mService.requestAutoFill(null, userId, null, flags);
         return 0;
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
new file mode 100644
index 0000000..08e81d3
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.autofill;
+
+import static android.view.View.AUTO_FILL_FLAG_TYPE_SAVE;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_FILL;
+
+import static com.android.server.autofill.AutoFillManagerService.DEBUG;
+
+import android.app.Activity;
+import android.app.AppGlobals;
+import android.app.Notification;
+import android.app.Notification.Action;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.service.autofill.AutoFillService;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import android.view.autofill.Dataset;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.FillResponse;
+import android.widget.Toast;
+
+import com.android.server.UiThread;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Handles all auto-fill related UI tasks.
+ */
+// TODO(b/33197203): document exactly what once the auto-fill bar is implemented
+final class AutoFillUI {
+
+    private static final String TAG = "AutoFillUI";
+
+    private final Context mContext;
+
+    AutoFillUI(Context context, AutoFillManagerService service, Object lock) {
+        mContext = context;
+        mResolver = context.getContentResolver();
+        mService = service;
+        mLock = lock;
+    }
+
+    /**
+     * Displays an error message to the user.
+     */
+    void showError(String message) {
+        // TODO(b/33197203): proper implementation
+        UiThread.getHandler().runWithScissors(() -> {
+            Toast.makeText(mContext, "AutoFill error: " + message, Toast.LENGTH_LONG).show();
+        }, 0);
+    }
+
+    /**
+     * Highlights in the {@link Activity} the fields saved by the service.
+     */
+    void highlightSavedFields(AutoFillId[] ids) {
+        // TODO(b/33197203): proper implementation (must be handled by activity)
+        UiThread.getHandler().runWithScissors(() -> {
+            Toast.makeText(mContext, "AutoFill: service saved ids " + Arrays.toString(ids),
+                    Toast.LENGTH_LONG).show();
+        }, 0);
+    }
+
+    /**
+     * Shows the options from a {@link FillResponse} so the user can pick up the proper
+     * {@link Dataset} (when the response has one).
+     */
+    void showOptions(int userId, int callbackId, FillResponse response) {
+        // TODO(b/33197203): proper implementation
+        // TODO(b/33197203): make sure if removes the callback from cache
+        showOptionsNotification(userId, callbackId, response);
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////
+    // TODO(b/33197203): temporary code using a notification to request auto-fill. //
+    // Will be removed once UX decide the right way to present it to the user.     //
+    /////////////////////////////////////////////////////////////////////////////////
+
+    // TODO(b/33197203): remove from frameworks/base/core/res/AndroidManifest.xml once not used
+    private static final String NOTIFICATION_AUTO_FILL_INTENT =
+            "com.android.internal.autofill.action.REQUEST_AUTOFILL";
+
+    // Extras used in the notification intents
+    private static final String EXTRA_USER_ID = "user_id";
+    private static final String EXTRA_NOTIFICATION_TYPE = "notification_type";
+    private static final String EXTRA_CALLBACK_ID = "callback_id";
+    private static final String EXTRA_FILL_RESPONSE = "fill_response";
+    private static final String EXTRA_DATASET = "dataset";
+
+    private static final String TYPE_EMULATE = "emulate";
+    private static final String TYPE_OPTIONS = "options";
+    private static final String TYPE_DELETE_CALLBACK = "delete_callback";
+    private static final String TYPE_PICK_DATASET = "pick_dataset";
+    private static final String TYPE_SAVE = "save";
+
+    static final int MSG_SHOW_ALL_NOTIFICATIONS = 42;
+    static final int SHOW_ALL_NOTIFICATIONS_DELAY_MS = 5000;
+
+    private BroadcastReceiver mNotificationReceiver;
+    private final ContentResolver mResolver;
+    private final AutoFillManagerService mService;
+    private final Object mLock;
+
+    // Hack used to generate unique pending intents
+    static int sResultCode = 0;
+
+    final class NotificationReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int userId = intent.getIntExtra(EXTRA_USER_ID, -1);
+
+            final AutoFillManagerServiceImpl service = mService.getServiceForUserLocked(userId);
+            if (service == null) {
+                Slog.w(TAG, "no auto-fill service for user " + userId);
+                return;
+            }
+
+            final int callbackId = intent.getIntExtra(EXTRA_CALLBACK_ID, -1);
+            final String type = intent.getStringExtra(EXTRA_NOTIFICATION_TYPE);
+            if (type == null) {
+                Slog.wtf(TAG, "No extra " + EXTRA_NOTIFICATION_TYPE + " on intent " + intent);
+                return;
+            }
+            final FillResponse fillData = intent.getParcelableExtra(EXTRA_FILL_RESPONSE);
+            final Dataset dataset = intent.getParcelableExtra(EXTRA_DATASET);
+            final Bundle datasetArgs = dataset == null ? null : dataset.getExtras();
+            final Bundle fillDataArgs = fillData == null ? null : fillData.getExtras();
+
+            // Bundle sent on AutoFillService methods - only set if service provided a bundle
+            final Bundle extras = (datasetArgs == null && fillDataArgs == null)
+                    ? null : new Bundle();
+
+            if (DEBUG) Slog.d(TAG, "Notification received: type=" + type + ", userId=" + userId
+                    + ", callbackId=" + callbackId);
+            synchronized (mLock) {
+                switch (type) {
+                    case TYPE_EMULATE:
+                        service.requestAutoFill(null, extras, AUTO_FILL_FLAG_TYPE_FILL);
+                        break;
+                    case TYPE_SAVE:
+                        if (datasetArgs != null) {
+                            if (DEBUG) Log.d(TAG, "filldata args on save notificataion: " +
+                                    bundleToString(fillDataArgs));
+                            extras.putBundle(AutoFillService.EXTRA_RESPONSE_EXTRAS, fillDataArgs);
+                        }
+                        if (dataset != null) {
+                            if (DEBUG) Log.d(TAG, "dataset args on save notificataion: " +
+                                    bundleToString(datasetArgs));
+                            extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetArgs);
+                        }
+                        service.requestAutoFill(null, extras, AUTO_FILL_FLAG_TYPE_SAVE);
+                        break;
+                    case TYPE_DELETE_CALLBACK:
+                        service.removeServerCallbackLocked(callbackId);
+                        break;
+                    case TYPE_PICK_DATASET:
+                        service.autoFillApp(callbackId, dataset);
+                        // Must cancel notification because it might be comming from action
+                        if (DEBUG) Log.d(TAG, "Cancelling notification");
+                        NotificationManager.from(mContext).cancel(TYPE_OPTIONS, userId);
+
+                        if (datasetArgs != null) {
+                            if (DEBUG) Log.d(TAG, "adding dataset's extra_data on save intent: "
+                                    + bundleToString(datasetArgs));
+                            extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetArgs);
+                        }
+
+                        // Also show notification with option to save the data
+                        showSaveNotification(userId, fillData, dataset);
+                        break;
+                    default: {
+                        Slog.w(TAG, "Unknown notification type: " + type);
+                    }
+                }
+            }
+        }
+    }
+
+    private ComponentName getProviderForUser(int userId) {
+        ComponentName serviceComponent = null;
+        ServiceInfo serviceInfo = null;
+        final String componentName = Settings.Secure.getStringForUser(
+                mResolver, Settings.Secure.AUTO_FILL_SERVICE, userId);
+        if (!TextUtils.isEmpty(componentName)) {
+            try {
+                serviceComponent = ComponentName.unflattenFromString(componentName);
+                serviceInfo =
+                        AppGlobals.getPackageManager().getServiceInfo(serviceComponent, 0, userId);
+            } catch (RuntimeException | RemoteException e) {
+                Slog.wtf(TAG, "Bad auto-fill service name " + componentName, e);
+                return null;
+            }
+        }
+
+        if (DEBUG) Slog.d(TAG, "getServiceComponentForUser(" + userId + "): component="
+                + serviceComponent + ", info: " + serviceInfo);
+        if (serviceInfo == null) {
+            Slog.w(TAG, "no service info for " + serviceComponent);
+            return null;
+        }
+        return serviceComponent;
+    }
+
+    void showAllNotifications() {
+        final UserManager userManager =
+                (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+        final List<UserInfo> allUsers = userManager.getUsers(true);
+
+        for (UserInfo user : allUsers) {
+            final ComponentName serviceComponent = getProviderForUser(user.id);
+            if (serviceComponent != null) {
+                showMainNotification(serviceComponent, user.id);
+            }
+        }
+    }
+
+    void updateNotification(int userId) {
+        final ComponentName serviceComponent = getProviderForUser(userId);
+        if (serviceComponent == null) {
+            cancelMainNotification(userId);
+        } else {
+            showMainNotification(serviceComponent, userId);
+        }
+    }
+
+    private static Intent newNotificationIntent(int userId, String type) {
+        final Intent intent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
+        intent.putExtra(EXTRA_USER_ID, userId);
+        intent.putExtra(EXTRA_NOTIFICATION_TYPE, type);
+        return intent;
+    }
+
+    private PendingIntent newPickDatasetPI(int userId, int callbackId, FillResponse response,
+            Dataset dataset) {
+        final int resultCode = ++ sResultCode;
+        if (DEBUG) Log.d(TAG, "newPickDatasetPI: userId=" + userId + ", callback=" + callbackId
+                + ", resultCode=" + resultCode);
+
+        final Intent intent = newNotificationIntent(userId, TYPE_PICK_DATASET);
+        intent.putExtra(EXTRA_CALLBACK_ID, callbackId);
+        intent.putExtra(EXTRA_FILL_RESPONSE, response);
+        intent.putExtra(EXTRA_DATASET, dataset);
+        return PendingIntent.getBroadcast(mContext, resultCode, intent,
+                PendingIntent.FLAG_ONE_SHOT);
+    }
+
+    private static String bundleToString(Bundle bundle) {
+        if (bundle == null) {
+            return "null";
+        }
+        final Set<String> keySet = bundle.keySet();
+        final StringBuilder builder = new StringBuilder("[Bundle with ").append(keySet.size())
+                .append(" keys:");
+        for (String key : keySet) {
+            final Object value = bundle.get(key);
+            builder.append(' ').append(key).append('=');
+            builder.append((value instanceof Object[])
+                    ? Arrays.toString((Objects[]) value) : value);
+        }
+        return builder.append(']').toString();
+    }
+
+    /**
+     * Shows a permanent notification that triggers the auto-fill workflow for the given user.
+     *
+     * <p>It emulates calling the auto-fill service when the IME is shown.
+     */
+    private void showMainNotification(ComponentName serviceComponent, int userId) {
+        if (DEBUG) Log.d(TAG, "showNotification() for " + userId + ": " + serviceComponent);
+
+        synchronized (mLock) {
+            if (mNotificationReceiver == null) {
+                mNotificationReceiver = new NotificationReceiver();
+                mContext.registerReceiver(mNotificationReceiver,
+                        new IntentFilter(NOTIFICATION_AUTO_FILL_INTENT));
+            }
+        }
+
+        final Intent fillIntent = newNotificationIntent(userId, TYPE_EMULATE);
+        final PendingIntent fillPendingIntent = PendingIntent.getBroadcast(mContext,
+                -1, fillIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+        final String packageName = serviceComponent.getPackageName();
+        String providerName = null;
+        final PackageManager pm = mContext.getPackageManager();
+        try {
+            final ApplicationInfo info = pm.getApplicationInfoAsUser(packageName, 0, userId);
+            if (info != null) {
+                providerName = pm.getApplicationLabel(info).toString();
+            }
+        } catch (Exception e) {
+            providerName = packageName;
+        }
+        final String title = "AutoFill IME Emulation";
+        final String subTitle = "Tap notification to start auto-fill workflow (by '" + providerName
+                + "' on top activity on user " + userId + ".\n"
+                + "Once provider replies, a new notification will show your options.";
+
+        final Notification notification = new Notification.Builder(mContext)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setOngoing(true)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setLocalOnly(true)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setContentTitle(title)
+                .setStyle(new Notification.BigTextStyle().bigText(subTitle))
+                .setContentIntent(fillPendingIntent)
+                .build();
+        NotificationManager.from(mContext).notify(TYPE_EMULATE, userId, notification);
+    }
+
+    /**
+     * Cancels the permament notification created by
+     * {@link #showMainNotification(ComponentName, int)}.
+     */
+    private void cancelMainNotification(int userId) {
+        if (DEBUG) Log.d(TAG, "cancelNotificationLocked(): " + userId);
+        NotificationManager.from(mContext).cancel(TYPE_EMULATE, userId);
+    }
+
+    /**
+     * Shows a notification with the results of an auto-fill request, using notications actions
+     * to emulate the auto-fill bar buttons displaying the dataset names.
+     */
+    private void showOptionsNotification(int userId, int callbackId, FillResponse response) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            showOptionsNotificationAsSystem(userId, callbackId, response);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private void showOptionsNotificationAsSystem(int userId, int callbackId,
+            FillResponse response) {
+        // Make sure server callback is removed from cache if user cancels the notification.
+        final Intent deleteIntent = newNotificationIntent(userId, TYPE_DELETE_CALLBACK);
+        deleteIntent.putExtra(EXTRA_CALLBACK_ID, callbackId);
+        final PendingIntent deletePendingIntent = PendingIntent.getBroadcast(mContext,
+                ++sResultCode, deleteIntent, PendingIntent.FLAG_ONE_SHOT);
+
+        final String title = "AutoFill Options";
+
+        final Notification.Builder notification = new Notification.Builder(mContext)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setOngoing(false)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setLocalOnly(true)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setDeleteIntent(deletePendingIntent)
+                .setContentTitle(title);
+
+        boolean autoCancel = true;
+        final String subTitle;
+        final List<Dataset> datasets;
+        final AutoFillId[] savableIds;
+        if (response != null) {
+            datasets = response.getDatasets();
+            savableIds = response.getSavableIds();
+        } else {
+            datasets = null;
+            savableIds = null;
+        }
+        boolean showSave = false;
+        if (datasets == null ) {
+            subTitle = "No options to auto-fill this activity.";
+        } else if (datasets.isEmpty()) {
+            if (savableIds.length == 0) {
+                subTitle = "No options to auto-fill this activity.";
+            } else {
+                subTitle = "No options to auto-fill this activity, but provider can save ids:\n"
+                        + Arrays.toString(savableIds);
+                showSave = true;
+            }
+        } else {
+            final AutoFillManagerServiceImpl service = mService.getServiceForUserLocked(userId);
+            if (service == null) {
+                subTitle = "No auto-fill service for user " + userId;
+                Slog.w(TAG, subTitle);
+            } else {
+                autoCancel = false;
+                final int size = datasets.size();
+                subTitle = "There are " + size + " option(s).\n"
+                        + "Use the notification action(s) to select the proper one.";
+                for (Dataset dataset : datasets) {
+                    final CharSequence name = dataset.getName();
+                    final PendingIntent pi = newPickDatasetPI(userId, callbackId, response, dataset);
+                    notification.addAction(new Action.Builder(null, name, pi).build());
+                }
+            }
+        }
+
+        notification.setAutoCancel(autoCancel);
+        notification.setStyle(new Notification.BigTextStyle().bigText(subTitle));
+
+        NotificationManager.from(mContext).notify(TYPE_OPTIONS, userId, notification.build());
+
+        if (showSave) {
+            showSaveNotification(userId, response, null);
+        }
+    }
+
+    private void showSaveNotification(int userId, FillResponse response, Dataset dataset) {
+        final Intent saveIntent = newNotificationIntent(userId, TYPE_SAVE);
+        saveIntent.putExtra(EXTRA_FILL_RESPONSE, response);
+        if (dataset != null) {
+            saveIntent.putExtra(EXTRA_DATASET, dataset);
+        }
+        final PendingIntent savePendingIntent = PendingIntent.getBroadcast(mContext,
+                ++sResultCode, saveIntent, PendingIntent.FLAG_ONE_SHOT);
+
+        final String title = "AutoFill Save";
+        final String subTitle = "Tap notification to ask provider to save fields: \n"
+                + Arrays.toString(response.getSavableIds());
+
+        final Notification notification = new Notification.Builder(mContext)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setAutoCancel(true)
+                .setOngoing(false)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setLocalOnly(true)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setContentTitle(title)
+                .setContentIntent(savePendingIntent)
+                .setStyle(new Notification.BigTextStyle().bigText(subTitle))
+                .build();
+        NotificationManager.from(mContext).notify(TYPE_SAVE, userId, notification);
+    }
+
+    /////////////////////////////////////////
+    // End of temporary notification code. //
+    /////////////////////////////////////////
+}
diff --git a/services/core/Android.mk b/services/core/Android.mk
index efadbef..1366b3b 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -24,7 +24,7 @@
     android.hardware.power@1.0-java \
     android.hardware.tv.cec@1.0-java
 
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
+LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2
 
 ifneq ($(INCREMENTAL_BUILDS),)
     LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index e7f1d16..2ca1b4e 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -218,6 +218,11 @@
         @Override
         public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
                 Bundle prevRestrictions) {
+            if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)
+                    && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) {
+                // The relevant restriction has not changed - do nothing.
+                return;
+            }
             final boolean bluetoothDisallowed =
                     newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
             if ((mEnable || mEnableExternal) && bluetoothDisallowed) {
@@ -228,6 +233,7 @@
                             e);
                 }
             }
+            updateOppLauncherComponentState(bluetoothDisallowed);
         }
     };
 
@@ -953,7 +959,9 @@
         UserManagerInternal userManagerInternal =
                 LocalServices.getService(UserManagerInternal.class);
         userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
-        if (isBluetoothDisallowed()) {
+        final boolean isBluetoothDisallowed = isBluetoothDisallowed();
+        updateOppLauncherComponentState(isBluetoothDisallowed);
+        if (isBluetoothDisallowed) {
             return;
         }
         if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
@@ -2011,6 +2019,24 @@
         }
     }
 
+    /**
+     * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
+     * offered to the user if Bluetooth is disallowed. Puts the component to its default state if
+     * Bluetooth is not disallowed.
+     *
+     * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user
+     * restriction was set.
+     */
+    private void updateOppLauncherComponentState(boolean bluetoothDisallowed) {
+        final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
+                "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
+        final int newState = bluetoothDisallowed
+                ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+        mContext.getPackageManager()
+                .setComponentEnabledSetting(oppLauncherComponent, newState, 0);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index cef459a..e23844c 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -301,7 +301,8 @@
 
                 // If we're not connected at all then create a new connection.
                 if (mServiceConnection == null) {
-                    mServiceConnection = new ScoringServiceConnection(componentName);
+                    mServiceConnection = new ScoringServiceConnection(componentName,
+                            scorerData.packageUid);
                 }
 
                 // Make sure the connection is connected (idempotent)
@@ -325,7 +326,7 @@
 
     @Override
     public boolean updateScores(ScoredNetwork[] networks) {
-        if (!mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid())) {
+        if (!isCallerActiveScorer(getCallingUid())) {
             throw new SecurityException("Caller with UID " + getCallingUid() +
                     " is not the active scorer.");
         }
@@ -389,7 +390,7 @@
     @Override
     public boolean clearScores() {
         // Only the active scorer or the system should be allowed to flush all scores.
-        if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
+        if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
             final long token = Binder.clearCallingIdentity();
             try {
                 clearInternal();
@@ -418,10 +419,39 @@
         return false;
     }
 
+    /**
+     * Determine whether the application with the given UID is the enabled scorer.
+     *
+     * @param callingUid the UID to check
+     * @return true if the provided UID is the active scorer, false otherwise.
+     */
+    @Override
+    public boolean isCallerActiveScorer(int callingUid) {
+        synchronized (mServiceConnectionLock) {
+            return mServiceConnection != null && mServiceConnection.mScoringAppUid == callingUid;
+        }
+    }
+
+    /**
+     * Obtain the package name of the current active network scorer.
+     *
+     * @return the full package name of the current active scorer, or null if there is no active
+     *         scorer.
+     */
+    @Override
+    public String getActiveScorerPackage() {
+        synchronized (mServiceConnectionLock) {
+            if (mServiceConnection != null) {
+                return mServiceConnection.mComponentName.getPackageName();
+            }
+        }
+        return null;
+    }
+
     @Override
     public void disableScoring() {
         // Only the active scorer or the system should be allowed to disable scoring.
-        if (mNetworkScorerAppManager.isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
+        if (isCallerActiveScorer(getCallingUid()) || isCallerSystemUid()) {
             // no-op for now but we could write to the setting if needed.
         } else {
             throw new SecurityException(
@@ -623,12 +653,14 @@
 
     private static class ScoringServiceConnection implements ServiceConnection {
         private final ComponentName mComponentName;
+        private final int mScoringAppUid;
         private volatile boolean mBound = false;
         private volatile boolean mConnected = false;
         private volatile INetworkRecommendationProvider mRecommendationProvider;
 
-        ScoringServiceConnection(ComponentName componentName) {
+        ScoringServiceConnection(ComponentName componentName, int scoringAppUid) {
             mComponentName = componentName;
+            mScoringAppUid = scoringAppUid;
         }
 
         void connect(Context context) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7682f91..3b2041e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -690,19 +690,21 @@
         public AssistStructure structure = null;
         public AssistContent content = null;
         public Bundle receiverExtras;
+        public int resultCode;
         public int flags;
 
         public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
-                String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _flags,
-                int _userHandle) {
+                String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _resultCode,
+                int _userHandle, int _flags) {
             activity = _activity;
             extras = _extras;
             intent = _intent;
             hint = _hint;
             receiver = _receiver;
             receiverExtras = _receiverExtras;
-            flags = _flags;
+            resultCode = _resultCode;
             userHandle = _userHandle;
+            flags = _flags;
         }
         @Override
         public void run() {
@@ -12190,7 +12192,7 @@
     @Override
     public Bundle getAssistContextExtras(int requestType) {
         PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
-                null, null, true /* focused */, true /* newSessionId */,
+                null, 0, null, true /* focused */, true /* newSessionId */,
                 UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT, 0);
         if (pae == null) {
             return null;
@@ -12258,22 +12260,37 @@
             Bundle receiverExtras,
             IBinder activityToken, boolean focused, boolean newSessionId) {
         return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
-                activityToken, focused, newSessionId,
-                UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT, 0)
-                != null;
+                0, activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null,
+                PENDING_ASSIST_EXTRAS_LONG_TIMEOUT, 0) != null;
     }
 
     @Override
     public boolean requestAutoFillData(IResultReceiver receiver, Bundle receiverExtras,
-            IBinder activityToken, int flags) {
-        return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_FULL, null, null, receiver,
-                receiverExtras, activityToken, true, true,
-                UserHandle.getCallingUserId(), null, PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT,
-                flags) != null;
+            int resultCode, IBinder activityToken, int flags) {
+        final boolean forFill = (flags & View.AUTO_FILL_FLAG_TYPE_FILL) != 0;
+        final boolean forSave = (flags & View.AUTO_FILL_FLAG_TYPE_SAVE) != 0;
+        if ((forFill && forSave) || (!forFill) && !(forSave)) {
+            // There can be only one!
+            Slog.w(TAG,  "requestAutoFillData(): invalid flags (" + flags + ")");
+            return false;
+        }
+
+        // NOTE: we could always use ActivityManager.ASSIST_CONTEXT_FULL and let ActivityThread
+        // rely on the flags to decide whether the handleRequestAssistContextExtras() is for
+        // auto-fill, but it's safer to explicitly use new AutoFill types, in case the Assist
+        // requests use flags in the future as well (since their flags value might collide with the
+        // auto-fill flag values).
+        final int type = forFill?
+                ActivityManager.ASSIST_CONTEXT_AUTO_FILL :
+                    ActivityManager.ASSIST_CONTEXT_AUTO_FILL_SAVE;
+
+        return enqueueAssistContext(type, null, null, receiver, receiverExtras, resultCode,
+                activityToken, true, true, UserHandle.getCallingUserId(), null,
+                PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT, flags) != null;
     }
 
     private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
-            IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken,
+            IResultReceiver receiver, Bundle receiverExtras, int resultCode, IBinder activityToken,
             boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout,
             int flags) {
         enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
@@ -12314,7 +12331,7 @@
             extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
             extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
             pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
-                    flags, userHandle);
+                    resultCode, userHandle, flags);
             // Increment the sessionId if necessary
             if (newSessionId) {
                 mViSessionId++;
@@ -12400,17 +12417,15 @@
                 if (pae.flags > 0) {
                     sendBundle.putInt(VoiceInteractionSession.KEY_FLAGS, pae.flags);
                 }
-                IBinder autoFillCallback =
-                        extras.getBinder(AutoFillService.KEY_CALLBACK);
-                if (autoFillCallback != null) {
-                    sendBundle.putBinder(AutoFillService.KEY_CALLBACK,
-                            autoFillCallback);
+                IBinder cb = extras.getBinder(AutoFillService.KEY_CALLBACK);
+                if (cb != null) {
+                    sendBundle.putBinder(AutoFillService.KEY_CALLBACK, cb);
                 }
             }
         }
         if (sendReceiver != null) {
             try {
-                sendReceiver.send(0, sendBundle);
+                sendReceiver.send(pae.resultCode, sendBundle);
             } catch (RemoteException e) {
             }
             return;
@@ -12435,9 +12450,9 @@
 
     public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
             Bundle args) {
-        return enqueueAssistContext(requestType, intent, hint, null, null, null,
-                true /* focused */, true /* newSessionId */,
-                userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT, 0) != null;
+        return enqueueAssistContext(requestType, intent, hint, null, null, 0, null,
+                true /* focused */, true /* newSessionId */, userHandle, args,
+                PENDING_ASSIST_EXTRAS_TIMEOUT, 0) != null;
     }
 
     public void registerProcessObserver(IProcessObserver observer) {
@@ -17875,6 +17890,11 @@
 
     private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
             String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
+        if ((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
+            // Don't yell about broadcasts sent via shell
+            return;
+        }
+
         final String action = intent.getAction();
         if (isProtectedBroadcast
                 || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
@@ -18018,11 +18038,7 @@
             case Process.PHONE_UID:
             case Process.BLUETOOTH_UID:
             case Process.NFC_UID:
-                if ((intent.getFlags() & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {
-                    isCallerSystem = false;
-                } else {
-                    isCallerSystem = true;
-                }
+                isCallerSystem = true;
                 break;
             default:
                 isCallerSystem = (callerApp != null) && callerApp.persistent;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 09af941..007a478 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -949,14 +949,18 @@
     }
 
     void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
-        // Trigger launch power hint if activity being launched is not in the current task
-        final ActivityStack focusStack = mSupervisor.getFocusedStack();
-        final ActivityRecord curTop = (focusStack == null)
-            ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
-        if ((forceSend || (!mPowerHintSent && curTop != null &&
-                curTop.task != null && mStartActivity != null &&
-                curTop.task != mStartActivity.task )) &&
-                mService.mLocalPowerManager != null) {
+        boolean sendHint = forceSend;
+
+        if (!sendHint) {
+            // If not forced, send power hint when the activity's process is different than the
+            // current resumed activity.
+            final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
+            sendHint = resumedActivity == null
+                || resumedActivity.app == null
+                || !resumedActivity.app.equals(mStartActivity.app);
+        }
+
+        if (sendHint && mService.mLocalPowerManager != null) {
             mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
             mPowerHintSent = true;
         }
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6d96a10..79567d5 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -199,7 +199,8 @@
         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
         mTetherMasterSM.start();
 
-        mUpstreamNetworkMonitor = new UpstreamNetworkMonitor();
+        mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
+                mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
 
         mStateReceiver = new StateReceiver();
         IntentFilter filter = new IntentFilter();
@@ -1027,38 +1028,6 @@
     }
 
     /**
-     * A NetworkCallback class that relays information of interest to the
-     * tethering master state machine thread for subsequent processing.
-     */
-    class UpstreamNetworkCallback extends NetworkCallback {
-        @Override
-        public void onAvailable(Network network) {
-            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
-                    UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network);
-        }
-
-        @Override
-        public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
-            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
-                    UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0,
-                    new NetworkState(null, null, newNc, network, null, null));
-        }
-
-        @Override
-        public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
-            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
-                    UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0,
-                    new NetworkState(null, newLp, null, network, null, null));
-        }
-
-        @Override
-        public void onLost(Network network) {
-            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
-                    UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network);
-        }
-    }
-
-    /**
      * A class to centralize all the network and link properties information
      * pertaining to the current and any potential upstream network.
      *
@@ -1072,21 +1041,31 @@
      * TODO: Investigate whether more "upstream-specific" logic/functionality
      * could/should be moved here.
      */
-    class UpstreamNetworkMonitor {
-        static final int EVENT_ON_AVAILABLE      = 1;
-        static final int EVENT_ON_CAPABILITIES   = 2;
-        static final int EVENT_ON_LINKPROPERTIES = 3;
-        static final int EVENT_ON_LOST           = 4;
+    public class UpstreamNetworkMonitor {
+        public static final int EVENT_ON_AVAILABLE      = 1;
+        public static final int EVENT_ON_CAPABILITIES   = 2;
+        public static final int EVENT_ON_LINKPROPERTIES = 3;
+        public static final int EVENT_ON_LOST           = 4;
 
-        final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
-        NetworkCallback mDefaultNetworkCallback;
-        NetworkCallback mDunTetheringCallback;
+        private final Context mContext;
+        private final StateMachine mTarget;
+        private final int mWhat;
+        private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
+        private ConnectivityManager mCM;
+        private NetworkCallback mDefaultNetworkCallback;
+        private NetworkCallback mDunTetheringCallback;
 
-        void start() {
+        public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
+            mContext = ctx;
+            mTarget = tgt;
+            mWhat = what;
+        }
+
+        public void start() {
             stop();
 
             mDefaultNetworkCallback = new UpstreamNetworkCallback();
-            getConnectivityManager().registerDefaultNetworkCallback(mDefaultNetworkCallback);
+            cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
 
             final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
                     .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -1094,29 +1073,28 @@
                     .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
                     .build();
             mDunTetheringCallback = new UpstreamNetworkCallback();
-            getConnectivityManager().registerNetworkCallback(
-                    dunTetheringRequest, mDunTetheringCallback);
+            cm().registerNetworkCallback(dunTetheringRequest, mDunTetheringCallback);
         }
 
-        void stop() {
+        public void stop() {
             if (mDefaultNetworkCallback != null) {
-                getConnectivityManager().unregisterNetworkCallback(mDefaultNetworkCallback);
+                cm().unregisterNetworkCallback(mDefaultNetworkCallback);
                 mDefaultNetworkCallback = null;
             }
 
             if (mDunTetheringCallback != null) {
-                getConnectivityManager().unregisterNetworkCallback(mDunTetheringCallback);
+                cm().unregisterNetworkCallback(mDunTetheringCallback);
                 mDunTetheringCallback = null;
             }
 
             mNetworkMap.clear();
         }
 
-        NetworkState lookup(Network network) {
+        public NetworkState lookup(Network network) {
             return (network != null) ? mNetworkMap.get(network) : null;
         }
 
-        NetworkState processCallback(int arg1, Object obj) {
+        public NetworkState processCallback(int arg1, Object obj) {
             switch (arg1) {
                 case EVENT_ON_AVAILABLE: {
                     final Network network = (Network) obj;
@@ -1128,7 +1106,7 @@
                                 new NetworkState(null, null, null, network, null, null));
                     }
 
-                    final ConnectivityManager cm = getConnectivityManager();
+                    final ConnectivityManager cm = cm();
 
                     if (mDefaultNetworkCallback != null) {
                         cm.requestNetworkCapabilities(mDefaultNetworkCallback);
@@ -1199,6 +1177,42 @@
                     return null;
             }
         }
+
+        // Fetch (and cache) a ConnectivityManager only if and when we need one.
+        private ConnectivityManager cm() {
+            if (mCM == null) {
+                mCM = mContext.getSystemService(ConnectivityManager.class);
+            }
+            return mCM;
+        }
+
+        /**
+         * A NetworkCallback class that relays information of interest to the
+         * tethering master state machine thread for subsequent processing.
+         */
+        private class UpstreamNetworkCallback extends NetworkCallback {
+            @Override
+            public void onAvailable(Network network) {
+                mTarget.sendMessage(mWhat, EVENT_ON_AVAILABLE, 0, network);
+            }
+
+            @Override
+            public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
+                mTarget.sendMessage(mWhat, EVENT_ON_CAPABILITIES, 0,
+                        new NetworkState(null, null, newNc, network, null, null));
+            }
+
+            @Override
+            public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
+                mTarget.sendMessage(mWhat, EVENT_ON_LINKPROPERTIES, 0,
+                        new NetworkState(null, newLp, null, network, null, null));
+            }
+
+            @Override
+            public void onLost(Network network) {
+                mTarget.sendMessage(mWhat, EVENT_ON_LOST, 0, network);
+            }
+        }
     }
 
     // Needed because the canonical source of upstream truth is just the
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 477ecdf..015345c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -577,6 +577,9 @@
                     brightness = mPowerRequest.dozeScreenBrightness;
                 }
                 break;
+            case DisplayPowerRequest.POLICY_VR:
+                state = Display.STATE_VR;
+                break;
             case DisplayPowerRequest.POLICY_DIM:
             case DisplayPowerRequest.POLICY_BRIGHT:
             default:
@@ -618,6 +621,7 @@
         // Animate the screen state change unless already animating.
         // The transition may be deferred, so after this point we will use the
         // actual state instead of the desired one.
+        final int oldState = mPowerState.getScreenState();
         animateScreenStateChange(state, performScreenOffTransition);
         state = mPowerState.getScreenState();
 
@@ -717,9 +721,10 @@
         }
 
         // Animate the screen brightness when the screen is on or dozing.
-        // Skip the animation when the screen is off or suspended.
+        // Skip the animation when the screen is off or suspended or transition to/from VR.
         if (!mPendingScreenOff) {
-            if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
+            boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
+            if ((state == Display.STATE_ON || state == Display.STATE_DOZE) && !wasOrWillBeInVr) {
                 animateScreenBrightness(brightness,
                         slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
             } else {
@@ -903,6 +908,23 @@
                 mPowerState.setColorFadeLevel(1.0f);
                 mPowerState.dismissColorFade();
             }
+        } else if (target == Display.STATE_VR) {
+            // Wait for brightness animation to complete beforehand when entering VR
+            // from screen on to prevent a perceptible jump because brightness may operate
+            // differently when the display is configured for dozing.
+            if (mScreenBrightnessRampAnimator.isAnimating()
+                    && mPowerState.getScreenState() == Display.STATE_ON) {
+                return;
+            }
+
+            // Set screen state.
+            if (!setScreenState(Display.STATE_VR)) {
+                return; // screen on blocked
+            }
+
+            // Dismiss the black surface without fanfare.
+            mPowerState.setColorFadeLevel(1.0f);
+            mPowerState.dismissColorFade();
         } else if (target == Display.STATE_DOZE) {
             // Want screen dozing.
             // Wait for brightness animation to complete beforehand when entering doze
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 61c2eac..8673225 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -471,6 +471,16 @@
                             }
                         }
 
+                        // If the state change was from or to VR, then we need to tell the light
+                        // so that it can apply appropriate VR brightness settings. This should
+                        // happen prior to changing the brightness but also if there is no
+                        // brightness change at all.
+                        if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
+                                currentState != state) {
+                            setVrMode(state == Display.STATE_VR);
+                        }
+
+
                         // Apply brightness changes given that we are in a non-suspended state.
                         if (brightnessChanged) {
                             setDisplayBrightness(brightness);
@@ -482,6 +492,15 @@
                         }
                     }
 
+                    private void setVrMode(boolean isVrEnabled) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "setVrMode("
+                                    + "id=" + displayId
+                                    + ", state=" + Display.stateToString(state) + ")");
+                        }
+                        mBacklight.setVrMode(isVrEnabled);
+                    }
+
                     private void setDisplayState(int state) {
                         if (DEBUG) {
                             Slog.d(TAG, "setDisplayState("
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/Light.java
index 0bab86b..b5ec603 100644
--- a/services/core/java/com/android/server/lights/Light.java
+++ b/services/core/java/com/android/server/lights/Light.java
@@ -46,4 +46,5 @@
     public abstract void pulse();
     public abstract void pulse(int color, int onMS);
     public abstract void turnOff();
+    public abstract void setVrMode(boolean enabled);
 }
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index bba0a50..e07156e 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -1,5 +1,4 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
+/* * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,18 +16,13 @@
 package com.android.server.lights;
 
 import com.android.server.SystemService;
-import com.android.server.vr.VrManagerService;
 
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
-import android.os.RemoteException;
 import android.os.Trace;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
 import android.util.Slog;
 
 public class LightsService extends SystemService {
@@ -36,7 +30,6 @@
     static final boolean DEBUG = false;
 
     final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
-    private boolean mVrModeEnabled;
 
     private final class LightImpl extends Light {
 
@@ -52,6 +45,13 @@
         @Override
         public void setBrightness(int brightness, int brightnessMode) {
             synchronized (this) {
+                // LOW_PERSISTENCE cannot be manually set
+                if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
+                    Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mId +
+                            ": brightness=0x" + Integer.toHexString(brightness));
+                    return;
+                }
+
                 int color = brightness & 0x000000ff;
                 color = 0xff000000 | (color << 16) | (color << 8) | color;
                 setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
@@ -80,11 +80,9 @@
         @Override
         public void pulse(int color, int onMS) {
             synchronized (this) {
-                if (mBrightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
-                    return;
-                }
                 if (mColor == 0 && !mFlashing) {
-                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
+                    setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000,
+                            BRIGHTNESS_MODE_USER);
                     mColor = 0;
                     mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
                 }
@@ -98,17 +96,23 @@
             }
         }
 
-        void enableLowPersistence() {
-            synchronized(this) {
-                setLightLocked(0, LIGHT_FLASH_NONE, 0, 0, BRIGHTNESS_MODE_LOW_PERSISTENCE);
-                mLocked = true;
-            }
-        }
+        @Override
+        public void setVrMode(boolean enabled) {
+            synchronized (this) {
+                if (mVrModeEnabled != enabled) {
+                    mVrModeEnabled = enabled;
 
-        void disableLowPersistence() {
-            synchronized(this) {
-                mLocked = false;
-                setLightLocked(mLastColor, LIGHT_FLASH_NONE, 0, 0, mLastBrightnessMode);
+                    mUseLowPersistenceForVR =
+                            (getVrDisplayMode() == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE);
+                    if (shouldBeInLowPersistenceMode()) {
+                        mLastBrightnessMode = mBrightnessMode;
+                    }
+
+                    // NOTE: We do not trigger a call to setLightLocked here.  We do not know the
+                    // current brightness or other values when leaving VR so we avoid any incorrect
+                    // jumps. The code that calls this method will immediately issue a brightness
+                    // update which is when the change will occur.
+                }
             }
         }
 
@@ -119,7 +123,13 @@
         }
 
         private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) {
-            if (!mLocked && (color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
+            if (shouldBeInLowPersistenceMode()) {
+                brightnessMode = BRIGHTNESS_MODE_LOW_PERSISTENCE;
+            } else if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
+                brightnessMode = mLastBrightnessMode;
+            }
+
+            if ((color != mColor || mode != mMode || onMS != mOnMS || offMS != mOffMS ||
                     mBrightnessMode != brightnessMode)) {
                 if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
                         + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
@@ -128,7 +138,6 @@
                 mMode = mode;
                 mOnMS = onMS;
                 mOffMS = offMS;
-                mLastBrightnessMode = mBrightnessMode;
                 mBrightnessMode = brightnessMode;
                 Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
                         + Integer.toHexString(color) + ")");
@@ -140,6 +149,10 @@
             }
         }
 
+        private boolean shouldBeInLowPersistenceMode() {
+            return mVrModeEnabled && mUseLowPersistenceForVR;
+        }
+
         private int mId;
         private int mColor;
         private int mMode;
@@ -149,7 +162,8 @@
         private int mBrightnessMode;
         private int mLastBrightnessMode;
         private int mLastColor;
-        private boolean mLocked;
+        private boolean mVrModeEnabled;
+        private boolean mUseLowPersistenceForVR;
     }
 
     public LightsService(Context context) {
@@ -167,17 +181,6 @@
 
     @Override
     public void onBootPhase(int phase) {
-        if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            IVrManager vrManager =
-                    (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
-            if (vrManager != null) {
-                try {
-                    vrManager.registerListener(mVrStateCallbacks);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Failed to register VR mode state listener: " + e);
-                }
-            }
-        }
     }
 
     private int getVrDisplayMode() {
@@ -188,30 +191,6 @@
                 currentUser);
     }
 
-    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
-        @Override
-        public void onVrStateChanged(boolean enabled) throws RemoteException {
-            LightImpl l = mLights[LightsManager.LIGHT_ID_BACKLIGHT];
-            int vrDisplayMode = getVrDisplayMode();
-
-            // User leaves VR mode before altering display settings.
-            if (enabled && vrDisplayMode == Settings.Secure.VR_DISPLAY_MODE_LOW_PERSISTENCE) {
-                if (!mVrModeEnabled) {
-                    if (DEBUG)
-                        Slog.v(TAG, "VR mode enabled, setting brightness to low persistence");
-                    l.enableLowPersistence();
-                    mVrModeEnabled = true;
-                }
-            } else {
-                if (mVrModeEnabled) {
-                    if (DEBUG) Slog.v(TAG, "VR mode disabled, resetting brightnes");
-                    l.disableLowPersistence();
-                    mVrModeEnabled = false;
-                }
-            }
-        }
-    };
-
     private final LightsManager mService = new LightsManager() {
         @Override
         public Light getLight(int id) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index dffe86a..ded8a1b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -55,7 +55,6 @@
 import android.app.AutomaticZenRule;
 import android.app.backup.BackupManager;
 import android.app.IActivityManager;
-import android.app.IOnNotificationChannelCreatedListener;
 import android.app.INotificationManager;
 import android.app.ITransientNotification;
 import android.app.Notification;
@@ -944,22 +943,16 @@
         mPackageManager = packageManager;
     }
 
-    // TODO: This probably should not be mocked, it's an implementation detail.
+    // TODO: Tests should call onStart instead once the methods above are removed.
     @VisibleForTesting
-    void setRankingHelper(RankingHelper rankingHelper) {
-        mRankingHelper = rankingHelper;
-    }
-
-    @Override
-    public void onStart() {
+    void init(IPackageManager packageManager, LightsManager lightsManager) {
         Resources resources = getContext().getResources();
-
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                 Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
                 DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE);
 
         mAm = ActivityManager.getService();
-        mPackageManager = AppGlobals.getPackageManager();
+        mPackageManager = packageManager;
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
         mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
         mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
@@ -1065,9 +1058,8 @@
             mStatusBar.setNotificationDelegate(mNotificationDelegate);
         }
 
-        final LightsManager lights = getLocalService(LightsManager.class);
-        mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
-        mAttentionLight = lights.getLight(LightsManager.LIGHT_ID_ATTENTION);
+        mNotificationLight = lightsManager.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
+        mAttentionLight = lightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
 
         mDefaultNotificationColor = resources.getColor(
                 R.color.config_defaultNotificationColor);
@@ -1134,7 +1126,11 @@
 
         mArchive = new Archive(resources.getInteger(
                 R.integer.config_notificationServiceArchiveSize));
+    }
 
+    @Override
+    public void onStart() {
+        init(AppGlobals.getPackageManager(), getLocalService(LightsManager.class));
         publishBinderService(Context.NOTIFICATION_SERVICE, mService);
         publishLocalService(NotificationManagerInternal.class, mInternalService);
     }
@@ -1514,13 +1510,18 @@
         }
 
         @Override
-        public void createNotificationChannel(String pkg, NotificationChannel channel,
-                IOnNotificationChannelCreatedListener listener) throws RemoteException {
+        public void createNotificationChannels(String pkg,
+                ParceledListSlice channelsList) throws RemoteException {
             checkCallerIsSystemOrSameApp(pkg);
-            mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel,
-                    true /* fromTargetApp */);
+            List<NotificationChannel> channels = channelsList.getList();
+            final int channelsSize = channels.size();
+            for (int i = 0; i < channelsSize; i++) {
+                final NotificationChannel channel = channels.get(i);
+                Preconditions.checkNotNull(channel, "channel in list is null");
+                mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel,
+                        true /* fromTargetApp */);
+            }
             savePolicyFile();
-            listener.onNotificationChannelCreated(channel);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 598ac2e..3fcce3c 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -434,7 +434,8 @@
         }
         if (r.channels.containsKey(channel.getId()) || channel.getName().equals(
                 mContext.getString(R.string.default_notification_channel_label))) {
-            throw new IllegalArgumentException("Channel already exists");
+            // Channel already exists, no-op.
+            return;
         }
         if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
                 || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 2bf5ef1..601a219 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -42,12 +42,18 @@
  * {@hide}
  */
 public class BackgroundDexOptService extends JobService {
-    static final String TAG = "BackgroundDexOptService";
+    private static final String TAG = "BackgroundDexOptService";
 
-    static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+    private static final boolean DEBUG = false;
 
-    static final int JOB_IDLE_OPTIMIZE = 800;
-    static final int JOB_POST_BOOT_UPDATE = 801;
+    private static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+
+    private static final int JOB_IDLE_OPTIMIZE = 800;
+    private static final int JOB_POST_BOOT_UPDATE = 801;
+
+    private static final long IDLE_OPTIMIZATION_PERIOD = DEBUG
+            ? TimeUnit.MINUTES.toMillis(1)
+            : TimeUnit.DAYS.toMillis(1);
 
     private static ComponentName sDexoptServiceName = new ComponentName(
             "android",
@@ -86,7 +92,7 @@
         js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
                     .setRequiresDeviceIdle(true)
                     .setRequiresCharging(true)
-                    .setPeriodic(TimeUnit.DAYS.toMillis(1))
+                    .setPeriodic(IDLE_OPTIMIZATION_PERIOD)
                     .build());
 
         if (DEBUG_DEXOPT) {
@@ -208,6 +214,7 @@
 
     private void idleOptimization(JobParameters jobParams, PackageManagerService pm,
             ArraySet<String> pkgs) {
+        Log.i(TAG, "Performing idle optimizations");
         // If post-boot update is still running, request that it exits early.
         mExitPostBootUpdate.set(true);
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 2e0199b..8c4a95c 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -217,26 +217,11 @@
                             dexoptNeeded);
                 }
 
-                final String dexoptType;
-                String oatDir = null;
-                boolean isOdexLocation = (dexoptNeeded < 0);
-                switch (Math.abs(dexoptNeeded)) {
-                    case DexFile.NO_DEXOPT_NEEDED:
-                        continue;
-                    case DexFile.DEX2OAT_FROM_SCRATCH:
-                    case DexFile.DEX2OAT_FOR_BOOT_IMAGE:
-                    case DexFile.DEX2OAT_FOR_FILTER:
-                    case DexFile.DEX2OAT_FOR_RELOCATION:
-                        dexoptType = "dex2oat";
-                        oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
-                        break;
-                    case DexFile.PATCHOAT_FOR_RELOCATION:
-                        dexoptType = "patchoat";
-                        break;
-                    default:
-                        throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
+                if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
+                    continue;
                 }
 
+                String oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
                 String sharedLibrariesPath = null;
                 if (sharedLibraries != null && sharedLibraries.length != 0) {
                     StringBuilder sb = new StringBuilder();
@@ -248,7 +233,7 @@
                     }
                     sharedLibrariesPath = sb.toString();
                 }
-                Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+                Log.i(TAG, "Running dexopt on: " + path + " pkg="
                         + pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
                         + " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
                         + " target-filter=" + targetCompilerFilter + " oatDir=" + oatDir
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index ddbc5fa..3085c9c 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -361,6 +361,11 @@
             }
             oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis());
 
+            // See ShortcutRequestPinProcessor.directPinShortcut().
+            if (mShortcutUser.mService.isDummyMainActivity(oldShortcut.getActivity())) {
+                oldShortcut.setActivity(null);
+            }
+
             return oldShortcut;
         } else {
             deleteShortcutInner(shortcutId);
@@ -1515,6 +1520,8 @@
 
         boolean failed = false;
 
+        final ShortcutService s = mShortcutUser.mService;
+
         final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all =
                 sortShortcutsToActivities();
 
@@ -1554,10 +1561,10 @@
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is both dynamic and manifest at the same time.");
             }
-            if (si.getActivity() == null) {
+            if (si.getActivity() == null && !si.isFloating()) {
                 failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
-                        + " has null activity.");
+                        + " has null activity, but not floating.");
             }
             if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
                 failed = true;
@@ -1579,6 +1586,11 @@
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has both resource and bitmap icons");
             }
+            if (s.isDummyMainActivity(si.getActivity())) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " has a dummy target activity");
+            }
         }
 
         if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index e815f0a..c8ddf0a 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -16,7 +16,6 @@
 package com.android.server.pm;
 
 import android.annotation.Nullable;
-import android.app.PendingIntent;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -209,7 +208,7 @@
         final boolean existsAlready = existing != null;
 
         if (DEBUG) {
-            Slog.d(TAG, "requestPinnedShortcut package=" + inShortcut.getPackage()
+            Slog.d(TAG, "requestPinnedShortcut: package=" + inShortcut.getPackage()
                     + " existsAlready=" + existsAlready
                     + " shortcut=" + inShortcut.toInsecureString());
         }
@@ -237,6 +236,14 @@
             // FLAG_PINNED is still set, if it's pinned by other launchers.
             shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED);
         } else {
+            // If the shortcut has no default activity, try to set the main activity.
+            // But in the request-pin case, it's optional, so it's okay even if the caller
+            // has no default activity.
+            if (inShortcut.getActivity() == null) {
+                inShortcut.setActivity(mService.injectGetDefaultMainActivity(
+                        inShortcut.getPackage(), inShortcut.getUserId()));
+            }
+
             // It doesn't exist, so it must have all mandatory fields.
             mService.validateShortcutForPinRequest(inShortcut);
 
@@ -244,12 +251,15 @@
             inShortcut.resolveResourceStrings(mService.injectGetResourcesForApplicationAsUser(
                     inShortcut.getPackage(), inShortcut.getUserId()));
             if (DEBUG) {
-                Slog.d(TAG, "resolved shortcut=" + inShortcut.toInsecureString());
+                Slog.d(TAG, "Resolved shortcut=" + inShortcut.toInsecureString());
             }
             // We should strip out the intent, but should preserve the icon.
             shortcutForLauncher = inShortcut.clone(
                     ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER_APPROVAL);
         }
+        if (DEBUG) {
+            Slog.d(TAG, "Sending to launcher=" + shortcutForLauncher.toInsecureString());
+        }
 
         // Create a request object.
         final PinShortcutRequestInner inner =
@@ -360,7 +370,9 @@
                 if (DEBUG) {
                     Slog.d(TAG, "Temporarily adding " + shortcutId + " as dynamic");
                 }
-                // Add as a dynamic shortcut.
+                // Add as a dynamic shortcut.  In order for a shortcut to be dynamic, it must
+                // have a target activity, so we set a dummy here.  It's later removed
+                // in deleteDynamicWithId().
                 if (original.getActivity() == null) {
                     original.setActivity(mService.getDummyMainActivity(appPackageName));
                 }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c02ce6e..a890526 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1604,7 +1604,7 @@
     private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate,
             boolean forPinRequest) {
         Preconditions.checkNotNull(shortcut, "Null shortcut detected");
-        if (!forPinRequest && shortcut.getActivity() != null) {
+        if (shortcut.getActivity() != null) {
             Preconditions.checkState(
                     shortcut.getPackage().equals(shortcut.getActivity().getPackageName()),
                     "Cannot publish shortcut: activity " + shortcut.getActivity() + " does not"
@@ -1618,10 +1618,8 @@
         if (!forUpdate) {
             shortcut.enforceMandatoryFields(/* forPinned= */ forPinRequest);
             if (!forPinRequest) {
-                Preconditions.checkArgument(
-                        injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()),
-                        "Cannot publish shortcut: " + shortcut.getActivity()
-                                + " is not main activity");
+                Preconditions.checkState(shortcut.getActivity() != null,
+                        "Cannot publish shortcut: target activity is not set");
             }
         }
         if (shortcut.getIcon() != null) {
@@ -1870,9 +1868,7 @@
             throwIfUserLockedL(userId);
 
             Preconditions.checkState(isUidForegroundLocked(injectBinderCallingUid()),
-                "Calling application must have a foreground activity or a foreground service");
-
-            // TODO Cancel all pending requests from the caller.
+                    "Calling application must have a foreground activity or a foreground service");
 
             // Send request to the launcher, if supported.
             ret = mShortcutRequestPinProcessor.requestPinItemLocked(shortcut, appWidget, userId,
@@ -3193,6 +3189,10 @@
         return new ComponentName(packageName, DUMMY_MAIN_ACTIVITY);
     }
 
+    boolean isDummyMainActivity(@Nullable ComponentName name) {
+        return name != null && DUMMY_MAIN_ACTIVITY.equals(name.getClassName());
+    }
+
     /**
      * Return all the enabled, exported and main activities from a package.
      */
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index fa1d991..0a312f0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -251,9 +251,9 @@
     static final boolean DEBUG_INPUT = false;
     static final boolean DEBUG_KEYGUARD = false;
     static final boolean DEBUG_LAYOUT = false;
-    static final boolean DEBUG_STARTING_WINDOW = false;
+    static final boolean DEBUG_SPLASH_SCREEN = false;
     static final boolean DEBUG_WAKEUP = false;
-    static final boolean SHOW_STARTING_ANIMATIONS = true;
+    static final boolean SHOW_SPLASH_SCREENS = true;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
     // No longer recommended for desk docks;
@@ -2794,10 +2794,10 @@
 
     /** {@inheritDoc} */
     @Override
-    public View addStartingWindow(IBinder appToken, String packageName, int theme,
-            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
-            int icon, int logo, int windowFlags, Configuration overrideConfig) {
-        if (!SHOW_STARTING_ANIMATIONS) {
+    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
+            CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
+            int logo, int windowFlags, Configuration overrideConfig) {
+        if (!SHOW_SPLASH_SCREENS) {
             return null;
         }
         if (packageName == null) {
@@ -2809,7 +2809,7 @@
 
         try {
             Context context = mContext;
-            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
+            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName
                     + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
                     + Integer.toHexString(theme));
             if (theme != context.getThemeResId() || labelRes != 0) {
@@ -2822,8 +2822,8 @@
             }
 
             if (overrideConfig != null && !overrideConfig.equals(EMPTY)) {
-                if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based"
-                        + " on overrideConfig" + overrideConfig + " for starting window");
+                if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based"
+                        + " on overrideConfig" + overrideConfig + " for splash screen");
                 final Context overrideContext = context.createConfigurationContext(overrideConfig);
                 overrideContext.setTheme(theme);
                 final TypedArray typedArray = overrideContext.obtainStyledAttributes(
@@ -2833,7 +2833,7 @@
                     // We want to use the windowBackground for the override context if it is
                     // available, otherwise we use the default one to make sure a themed starting
                     // window is displayed for the app.
-                    if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig"
+                    if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig"
                             + overrideConfig + " to starting window resId=" + resId);
                     context = overrideContext;
                 }
@@ -2895,19 +2895,19 @@
                 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
             }
 
-            params.setTitle("Starting " + packageName);
+            params.setTitle("Splash Screen " + packageName);
 
             wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
             view = win.getDecorView();
 
-            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for "
+            if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for "
                 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null));
 
             wm.addView(view, params);
 
             // Only return the view if it was successfully added to the
             // window manager... which we can tell by it having a parent.
-            return view.getParent() != null ? view : null;
+            return view.getParent() != null ? new SplashScreenSurface(view) : null;
         } catch (WindowManager.BadTokenException e) {
             // ignore
             Log.w(TAG, appToken + " already running, starting window not displayed. " +
@@ -2929,13 +2929,13 @@
 
     /** {@inheritDoc} */
     @Override
-    public void removeStartingWindow(IBinder appToken, View window) {
-        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
-                + window + " Callers=" + Debug.getCallers(4));
+    public void removeSplashScreen(IBinder appToken, StartingSurface surface) {
+        if (DEBUG_SPLASH_SCREEN) Slog.v(TAG, "Removing splash screen window for " + appToken + ": "
+                + surface + " Callers=" + Debug.getCallers(4));
 
-        if (window != null) {
+        if (surface != null) {
             WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-            wm.removeView(window);
+            wm.removeView(((SplashScreenSurface) surface).view);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/SplashScreenSurface.java b/services/core/java/com/android/server/policy/SplashScreenSurface.java
new file mode 100644
index 0000000..d421291
--- /dev/null
+++ b/services/core/java/com/android/server/policy/SplashScreenSurface.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.policy;
+
+import android.view.View;
+import android.view.WindowManagerPolicy;
+import android.view.WindowManagerPolicy.StartingSurface;
+
+import com.android.internal.policy.DecorView;
+import com.android.internal.policy.PhoneWindow;
+
+/**
+ * Holds the contents of a splash screen starting window, i.e. the {@link DecorView} of a
+ * {@link PhoneWindow}. This is just a wrapper such that we can return it from
+ * {@link WindowManagerPolicy#addSplashScreen}.
+ */
+class SplashScreenSurface implements StartingSurface {
+
+    final View view;
+
+    SplashScreenSurface(View view) {
+        this.view = view;
+    }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f2ccac5..8aefebc 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -136,6 +136,8 @@
     private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
     // Dirty bit: sQuiescent changed
     private static final int DIRTY_QUIESCENT = 1 << 12;
+    // Dirty bit: VR Mode enabled changed
+    private static final int DIRTY_VR_MODE_CHANGED = 1 << 13;
 
     // Summarizes the state of all active wakelocks.
     private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -413,11 +415,15 @@
     private int mScreenBrightnessSettingMinimum;
     private int mScreenBrightnessSettingMaximum;
     private int mScreenBrightnessSettingDefault;
+    private int mScreenBrightnessForVrSettingDefault;
 
     // The screen brightness setting, from 0 to 255.
     // Use -1 if no value has been set.
     private int mScreenBrightnessSetting;
 
+    // The screen brightness setting, from 0 to 255, to be used while in VR Mode.
+    private int mScreenBrightnessForVrSetting;
+
     // The screen auto-brightness adjustment setting, from -1 to 1.
     // Use 0 if there is no adjustment.
     private float mScreenAutoBrightnessAdjustmentSetting;
@@ -511,6 +517,9 @@
     // True if brightness should be affected by twilight.
     private boolean mBrightnessUseTwilight;
 
+    // True if we are currently in VR Mode.
+    private boolean mIsVrModeEnabled;
+
     private native void nativeInit();
 
     private static native void nativeAcquireSuspendBlocker(String name);
@@ -594,6 +603,7 @@
             mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
             mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
             mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+            mScreenBrightnessForVrSettingDefault = pm.getDefaultScreenBrightnessForVrSetting();
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
 
@@ -640,6 +650,9 @@
                     Settings.System.SCREEN_BRIGHTNESS),
                     false, mSettingsObserver, UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_BRIGHTNESS_MODE),
                     false, mSettingsObserver, UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
@@ -773,11 +786,17 @@
             }
         }
 
-        final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
+        final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
+
+        mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
+                Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mScreenBrightnessForVrSettingDefault,
+                UserHandle.USER_CURRENT);
+
         mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
                 Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
                 UserHandle.USER_CURRENT);
-        if (oldScreenBrightnessSetting != mScreenBrightnessSetting) {
+
+        if (oldScreenBrightnessSetting != getCurrentBrightnessSettingLocked()) {
             mTemporaryScreenBrightnessSettingOverride = -1;
         }
 
@@ -811,6 +830,10 @@
         mDirty |= DIRTY_SETTINGS;
     }
 
+    private int getCurrentBrightnessSettingLocked() {
+        return mIsVrModeEnabled ? mScreenBrightnessForVrSetting : mScreenBrightnessSetting;
+    }
+
     private void postAfterBootCompleted(Runnable r) {
         if (mBootCompleted) {
             BackgroundThread.getHandler().post(r);
@@ -2069,6 +2092,7 @@
                 || !mDreamsSupportedConfig
                 || !mDreamsEnabledSetting
                 || !mDisplayPowerRequest.isBrightOrDim()
+                || mDisplayPowerRequest.isVr()
                 || (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
                         | USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0
                 || !mBootCompleted) {
@@ -2113,7 +2137,8 @@
         final boolean oldDisplayReady = mDisplayReady;
         if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                 | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
-                | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_QUIESCENT)) != 0) {
+                | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
+                DIRTY_QUIESCENT)) != 0) {
             mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
 
             // Determine appropriate screen brightness and auto-brightness adjustments.
@@ -2127,6 +2152,9 @@
                 // bootloader brightness and the default brightness to be identical.
                 autoBrightness = false;
                 brightnessSetByUser = false;
+            } else if (mIsVrModeEnabled) {
+                screenBrightness = mScreenBrightnessForVrSetting;
+                autoBrightness = false;
             } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                 screenBrightness = mScreenBrightnessOverrideFromWindowManager;
                 autoBrightness = false;
@@ -2160,7 +2188,7 @@
             mDisplayPowerRequest.useAutoBrightness = autoBrightness;
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
             mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
-            mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
+            mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
             mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
 
             if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
@@ -2191,6 +2219,7 @@
                         + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
                         + ", mBootCompleted=" + mBootCompleted
                         + ", mScreenBrightnessBoostInProgress=" + mScreenBrightnessBoostInProgress
+                        + ", mIsVrModeEnabled= " + mIsVrModeEnabled
                         + ", sQuiescent=" + sQuiescent);
             }
         }
@@ -2220,6 +2249,10 @@
         }
     }
 
+    private boolean shouldBoostScreenBrightness() {
+        return !mIsVrModeEnabled && mScreenBrightnessBoostInProgress;
+    }
+
     private static boolean isValidBrightness(int value) {
         return value >= 0 && value <= 255;
     }
@@ -2230,6 +2263,10 @@
     }
 
     private int getDesiredScreenPolicyLocked() {
+        if (mIsVrModeEnabled) {
+            return DisplayPowerRequest.POLICY_VR;
+        }
+
         if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
             return DisplayPowerRequest.POLICY_OFF;
         }
@@ -2333,7 +2370,7 @@
     };
 
     private boolean shouldUseProximitySensorLocked() {
-        return (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
+        return !mIsVrModeEnabled && (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
     }
 
     /**
@@ -3085,7 +3122,11 @@
             pw.println("  mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
             pw.println("  mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
             pw.println("  mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+            pw.println("  mScreenBrightnessForVrSettingDefault="
+                    + mScreenBrightnessForVrSettingDefault);
+            pw.println("  mScreenBrightnessForVrSetting=" + mScreenBrightnessForVrSetting);
             pw.println("  mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
+            pw.println("  mIsVrModeEnabled=" + mIsVrModeEnabled);
 
             final int sleepTimeout = getSleepTimeoutLocked();
             final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
@@ -3223,6 +3264,14 @@
         @Override
         public void onVrStateChanged(boolean enabled) {
             powerHintInternal(PowerHint.VR_MODE, enabled ? 1 : 0);
+
+            synchronized (mLock) {
+                if (mIsVrModeEnabled != enabled) {
+                    mIsVrModeEnabled = enabled;
+                    mDirty |= DIRTY_VR_MODE_CHANGED;
+                    updatePowerStateLocked();
+                }
+            }
         }
     };
 
@@ -3975,6 +4024,7 @@
                 case Display.STATE_DOZE:
                 case Display.STATE_DOZE_SUSPEND:
                 case Display.STATE_ON:
+                case Display.STATE_VR:
                     break;
                 default:
                     screenState = Display.STATE_UNKNOWN;
diff --git a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
index b260e4e..b704eb1 100644
--- a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
@@ -20,7 +20,7 @@
 
 import java.io.File;
 import java.io.IOException;
-import libcore.tzdata.update.TzDataBundleInstaller;
+import libcore.tzdata.update2.TimeZoneBundleInstaller;
 
 /**
  * An install receiver responsible for installing timezone data updates.
@@ -29,18 +29,19 @@
 
     private static final String TAG = "TZDataInstallReceiver";
 
+    private static final File SYSTEM_TZ_DATA_FILE = new File("/system/usr/share/zoneinfo/tzdata");
     private static final File TZ_DATA_DIR = new File("/data/misc/zoneinfo");
     private static final String UPDATE_DIR_NAME = TZ_DATA_DIR.getPath() + "/updates/";
     private static final String UPDATE_METADATA_DIR_NAME = "metadata/";
     private static final String UPDATE_VERSION_FILE_NAME = "version";
     private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_bundle.zip";
 
-    private final TzDataBundleInstaller installer;
+    private final TimeZoneBundleInstaller installer;
 
     public TzDataInstallReceiver() {
         super(UPDATE_DIR_NAME, UPDATE_CONTENT_FILE_NAME, UPDATE_METADATA_DIR_NAME,
                 UPDATE_VERSION_FILE_NAME);
-        installer = new TzDataBundleInstaller(TAG, TZ_DATA_DIR);
+        installer = new TimeZoneBundleInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 35004c2..cab39b5 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -27,21 +27,21 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.ADD_STARTING;
-
-import android.graphics.Bitmap;
-import android.os.Trace;
-import com.android.server.AttributeCache;
 
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.graphics.Bitmap;
 import android.os.Binder;
 import android.os.Debug;
+import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
+import android.os.Looper;
+import android.os.Trace;
 import android.util.Slog;
 import android.view.IApplicationToken;
+import android.view.WindowManagerPolicy.StartingSurface;
 
+import com.android.server.AttributeCache;
 /**
  * Controller for the app window token container. This is created by activity manager to link
  * activity records to the app window token container they use in window manager.
@@ -52,6 +52,7 @@
         extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
 
     private final IApplicationToken mToken;
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
 
     private final Runnable mOnWindowsDrawn = () -> {
         if (mListener == null) {
@@ -80,6 +81,94 @@
         mListener.onWindowsGone();
     };
 
+    private final Runnable mAddStartingWindow = () -> {
+        final StartingData startingData;
+        final Configuration mergedOverrideConfiguration;
+
+        synchronized (mWindowMap) {
+            startingData = mContainer.startingData;
+            mergedOverrideConfiguration = mContainer.getMergedOverrideConfiguration();
+        }
+
+        if (startingData == null) {
+            // Animation has been canceled... do nothing.
+            return;
+        }
+
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
+                + this + ": pkg=" + mContainer.startingData.pkg);
+
+        StartingSurface contents = null;
+        try {
+            contents = mService.mPolicy.addSplashScreen(mContainer.token, startingData.pkg,
+                    startingData.theme, startingData.compatInfo, startingData.nonLocalizedLabel,
+                    startingData.labelRes, startingData.icon, startingData.logo,
+                    startingData.windowFlags, mergedOverrideConfiguration);
+        } catch (Exception e) {
+            Slog.w(TAG_WM, "Exception when adding starting window", e);
+        }
+        if (contents != null) {
+            boolean abort = false;
+
+            synchronized(mWindowMap) {
+                if (mContainer.removed || mContainer.startingData == null) {
+                    // If the window was successfully added, then
+                    // we need to remove it.
+                    if (mContainer.startingWindow != null) {
+                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+                                "Aborted starting " + mContainer
+                                        + ": removed=" + mContainer.removed
+                                        + " startingData=" + mContainer.startingData);
+                        mContainer.startingWindow = null;
+                        mContainer.startingData = null;
+                        abort = true;
+                    }
+                } else {
+                    mContainer.startingSurface = contents;
+                }
+                if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
+                        "Added starting " + mContainer
+                                + ": startingWindow="
+                                + mContainer.startingWindow + " startingView="
+                                + mContainer.startingSurface);
+            }
+
+            if (abort) {
+                try {
+                    mService.mPolicy.removeSplashScreen(mContainer.token, contents);
+                } catch (Exception e) {
+                    Slog.w(TAG_WM, "Exception when removing starting window", e);
+                }
+            }
+        }
+    };
+
+    private final Runnable mRemoveStartingWindow = () -> {
+        IBinder token = null;
+        StartingSurface contents = null;
+        synchronized (mWindowMap) {
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting "
+                    + mContainer + ": startingWindow="
+                    + mContainer.startingWindow + " startingView="
+                    + mContainer.startingSurface);
+            if (mContainer.startingWindow != null) {
+                contents = mContainer.startingSurface;
+                token = mContainer.token;
+                mContainer.startingData = null;
+                mContainer.startingSurface = null;
+                mContainer.startingWindow = null;
+                mContainer.startingDisplayed = false;
+            }
+        }
+        if (contents != null) {
+            try {
+                mService.mPolicy.removeSplashScreen(token, contents);
+            } catch (Exception e) {
+                Slog.w(TAG_WM, "Exception when removing starting window", e);
+            }
+        }
+    };
+
     public AppWindowContainerController(IApplicationToken token,
             AppWindowContainerListener listener, int taskId, int index, int requestedOrientation,
             boolean fullscreen, boolean showForAllUsers, int configChanges,
@@ -393,19 +482,42 @@
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
             mContainer.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
                     labelRes, icon, logo, windowFlags);
-            final Message m = mService.mH.obtainMessage(ADD_STARTING, mContainer);
-            // Note: we really want to do sendMessageAtFrontOfQueue() because we
-            // want to process the message ASAP, before any other queued
-            // messages.
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
-            mService.mH.sendMessageAtFrontOfQueue(m);
+            scheduleAddStartingWindow();
         }
         return true;
     }
 
+    void scheduleAddStartingWindow() {
+
+        // Note: we really want to do sendMessageAtFrontOfQueue() because we
+        // want to process the message ASAP, before any other queued
+        // messages.
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
+        mHandler.postAtFrontOfQueue(mAddStartingWindow);
+    }
+
     public void removeStartingWindow() {
         synchronized (mWindowMap) {
-            mService.scheduleRemoveStartingWindowLocked(mContainer);
+            if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
+                // Already scheduled.
+                return;
+            }
+
+            if (mContainer.startingWindow == null) {
+                if (mContainer.startingData != null) {
+                    // Starting window has not been added yet, but it is scheduled to be added.
+                    // Go ahead and cancel the request.
+                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+                            "Clearing startingData for token=" + mContainer);
+                    mContainer.startingData = null;
+                }
+                return;
+            }
+
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1)
+                    + ": Schedule remove starting " + mContainer
+                    + " startingWindow=" + mContainer.startingWindow);
+            mHandler.post(mRemoveStartingWindow);
         }
     }
 
@@ -508,15 +620,15 @@
 
 
     void reportWindowsDrawn() {
-        mService.mH.post(mOnWindowsDrawn);
+        mHandler.post(mOnWindowsDrawn);
     }
 
     void reportWindowsVisible() {
-        mService.mH.post(mOnWindowsVisible);
+        mHandler.post(mOnWindowsVisible);
     }
 
     void reportWindowsGone() {
-        mService.mH.post(mOnWindowsGone);
+        mHandler.post(mOnWindowsGone);
     }
 
     /** Calls directly into activity manager so window manager lock shouldn't held. */
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 0a48758..f4fa220 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -29,9 +29,9 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -47,22 +47,21 @@
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.logWithStack;
 
-import android.os.Debug;
-import com.android.internal.util.ToBooleanFunction;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.wm.WindowManagerService.H;
-
 import android.annotation.NonNull;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
+import android.os.Debug;
 import android.os.IBinder;
-import android.os.Message;
 import android.os.SystemClock;
 import android.util.Slog;
 import android.view.IApplicationToken;
-import android.view.View;
 import android.view.WindowManager;
+import android.view.WindowManagerPolicy.StartingSurface;
+
+import com.android.internal.util.ToBooleanFunction;
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.wm.WindowManagerService.H;
 
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
@@ -138,7 +137,7 @@
     // Information about an application starting window if displayed.
     StartingData startingData;
     WindowState startingWindow;
-    View startingView;
+    StartingSurface startingSurface;
     boolean startingDisplayed;
     boolean startingMoved;
     boolean firstWindowDrawn;
@@ -213,8 +212,9 @@
             // it from behind the starting window, so there is no need for it to also be doing its
             // own stuff.
             winAnimator.clearAnimation();
-            winAnimator.mService.mFinishedStarting.add(this);
-            winAnimator.mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+            if (getController() != null) {
+                getController().removeStartingWindow();
+            }
         }
         updateReportedVisibilityLocked();
     }
@@ -439,8 +439,6 @@
     }
 
     void onRemovedFromDisplay() {
-        AppWindowToken startingToken = null;
-
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
 
         boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
@@ -461,6 +459,10 @@
         if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
                 + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
 
+        if (startingData != null && getController() != null) {
+            getController().removeStartingWindow();
+        }
+
         final TaskStack stack = mTask.mStack;
         if (delayed && !isEmpty()) {
             // set the token aside because it has an active animation to be finished
@@ -477,9 +479,6 @@
         }
 
         removed = true;
-        if (startingData != null) {
-            startingToken = this;
-        }
         stopFreezingScreen(true, true);
         if (mService.mFocusedApp == this) {
             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
@@ -491,9 +490,6 @@
         if (!delayed) {
             updateReportedVisibilityLocked();
         }
-
-        // Will only remove if startingToken non null.
-        mService.scheduleRemoveStartingWindowLocked(startingToken);
     }
 
     void clearAnimatingFlags() {
@@ -557,7 +553,9 @@
         mAppStopped = true;
         destroySurfaces();
         // Remove any starting window that was added for this app if they are still around.
-        mTask.mService.scheduleRemoveStartingWindowLocked(this);
+        if (getController() != null) {
+            getController().removeStartingWindow();
+        }
     }
 
     /**
@@ -667,16 +665,20 @@
         // TODO: Something smells about the code below...Is there a better way?
         if (startingWindow == win) {
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
-            mService.scheduleRemoveStartingWindowLocked(this);
+            if (getController() != null) {
+                getController().removeStartingWindow();
+            }
         } else if (mChildren.size() == 0 && startingData != null) {
             // If this is the last window and we had requested a starting transition window,
             // well there is no point now.
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
             startingData = null;
-        } else if (mChildren.size() == 1 && startingView != null) {
+        } else if (mChildren.size() == 1 && startingSurface != null) {
             // If this is the last window except for a starting transition window,
             // we need to get rid of the starting transition.
-            mService.scheduleRemoveStartingWindowLocked(this);
+            if (getController() != null) {
+                getController().removeStartingWindow();
+            }
         }
     }
 
@@ -1015,7 +1017,7 @@
         }
 
         final WindowState tStartingWindow = fromToken.startingWindow;
-        if (tStartingWindow != null && fromToken.startingView != null) {
+        if (tStartingWindow != null && fromToken.startingSurface != null) {
             // In this case, the starting icon has already been displayed, so start
             // letting windows get shown immediately without any more transitions.
             mService.mSkipAppTransitionAnimation = true;
@@ -1027,13 +1029,13 @@
 
             // Transfer the starting window over to the new token.
             startingData = fromToken.startingData;
-            startingView = fromToken.startingView;
+            startingSurface = fromToken.startingSurface;
             startingDisplayed = fromToken.startingDisplayed;
             fromToken.startingDisplayed = false;
             startingWindow = tStartingWindow;
             reportedVisible = fromToken.reportedVisible;
             fromToken.startingData = null;
-            fromToken.startingView = null;
+            fromToken.startingSurface = null;
             fromToken.startingWindow = null;
             fromToken.startingMoved = true;
             tStartingWindow.mToken = this;
@@ -1080,10 +1082,9 @@
             startingData = fromToken.startingData;
             fromToken.startingData = null;
             fromToken.startingMoved = true;
-            final Message m = mService.mH.obtainMessage(H.ADD_STARTING, this);
-            // Note: we really want to do sendMessageAtFrontOfQueue() because we want to process the
-            // message ASAP, before any other queued messages.
-            mService.mH.sendMessageAtFrontOfQueue(m);
+            if (getController() != null) {
+                getController().scheduleAddStartingWindow();
+            }
             return true;
         }
 
@@ -1421,10 +1422,10 @@
                     pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
                     pw.print(" mIsExiting="); pw.println(mIsExiting);
         }
-        if (startingWindow != null || startingView != null
+        if (startingWindow != null || startingSurface != null
                 || startingDisplayed || startingMoved) {
             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
-                    pw.print(" startingView="); pw.print(startingView);
+                    pw.print(" startingSurface="); pw.print(startingSurface);
                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
                     pw.print(" startingMoved="); pw.println(startingMoved);
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index dc06d12..775d8a0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -498,7 +498,10 @@
                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
                             "RECOVER DESTROY", false);
                     winAnimator.destroySurface();
-                    mService.scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken);
+                    if (winAnimator.mWin.mAppToken != null
+                            && winAnimator.mWin.mAppToken.getController() != null) {
+                        winAnimator.mWin.mAppToken.getController().removeStartingWindow();
+                    }
                 }
 
                 try {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 38cb543..4e25935 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2851,33 +2851,6 @@
         }
     }
 
-    void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) {
-        if (wtoken == null) {
-            return;
-        }
-        if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) {
-            // Already scheduled.
-            return;
-        }
-
-        if (wtoken.startingWindow == null) {
-            if (wtoken.startingData != null) {
-                // Starting window has not been added yet, but it is scheduled to be added.
-                // Go ahead and cancel the request.
-                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
-                        "Clearing startingData for token=" + wtoken);
-                wtoken.startingData = null;
-            }
-            return;
-        }
-
-        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) +
-                ": Schedule remove starting " + wtoken + (wtoken != null ?
-                " startingWindow=" + wtoken.startingWindow : ""));
-        Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
-        mH.sendMessage(m);
-    }
-
     public void moveTaskToTop(int taskId) {
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -5578,9 +5551,6 @@
         public static final int REPORT_FOCUS_CHANGE = 2;
         public static final int REPORT_LOSING_FOCUS = 3;
         public static final int DO_TRAVERSAL = 4;
-        public static final int ADD_STARTING = 5;
-        public static final int REMOVE_STARTING = 6;
-        public static final int FINISHED_STARTING = 7;
         public static final int WINDOW_FREEZE_TIMEOUT = 11;
 
         public static final int APP_TRANSITION_TIMEOUT = 13;
@@ -5722,126 +5692,6 @@
                     }
                 } break;
 
-                case ADD_STARTING: {
-                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
-                    final StartingData sd = wtoken.startingData;
-
-                    if (sd == null) {
-                        // Animation has been canceled... do nothing.
-                        return;
-                    }
-
-                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
-                            + wtoken + ": pkg=" + sd.pkg);
-
-                    View view = null;
-                    try {
-                        view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
-                            sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
-                            sd.windowFlags, wtoken.getMergedOverrideConfiguration());
-                    } catch (Exception e) {
-                        Slog.w(TAG_WM, "Exception when adding starting window", e);
-                    }
-
-                    if (view != null) {
-                        boolean abort = false;
-
-                        synchronized(mWindowMap) {
-                            if (wtoken.removed || wtoken.startingData == null) {
-                                // If the window was successfully added, then
-                                // we need to remove it.
-                                if (wtoken.startingWindow != null) {
-                                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
-                                            "Aborted starting " + wtoken
-                                            + ": removed=" + wtoken.removed
-                                            + " startingData=" + wtoken.startingData);
-                                    wtoken.startingWindow = null;
-                                    wtoken.startingData = null;
-                                    abort = true;
-                                }
-                            } else {
-                                wtoken.startingView = view;
-                            }
-                            if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
-                                    "Added starting " + wtoken
-                                    + ": startingWindow="
-                                    + wtoken.startingWindow + " startingView="
-                                    + wtoken.startingView);
-                        }
-
-                        if (abort) {
-                            try {
-                                mPolicy.removeStartingWindow(wtoken.token, view);
-                            } catch (Exception e) {
-                                Slog.w(TAG_WM, "Exception when removing starting window", e);
-                            }
-                        }
-                    }
-                } break;
-
-                case REMOVE_STARTING: {
-                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
-                    IBinder token = null;
-                    View view = null;
-                    synchronized (mWindowMap) {
-                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting "
-                                + wtoken + ": startingWindow="
-                                + wtoken.startingWindow + " startingView="
-                                + wtoken.startingView);
-                        if (wtoken.startingWindow != null) {
-                            view = wtoken.startingView;
-                            token = wtoken.token;
-                            wtoken.startingData = null;
-                            wtoken.startingView = null;
-                            wtoken.startingWindow = null;
-                            wtoken.startingDisplayed = false;
-                        }
-                    }
-                    if (view != null) {
-                        try {
-                            mPolicy.removeStartingWindow(token, view);
-                        } catch (Exception e) {
-                            Slog.w(TAG_WM, "Exception when removing starting window", e);
-                        }
-                    }
-                } break;
-
-                case FINISHED_STARTING: {
-                    IBinder token = null;
-                    View view = null;
-                    while (true) {
-                        synchronized (mWindowMap) {
-                            final int N = mFinishedStarting.size();
-                            if (N <= 0) {
-                                break;
-                            }
-                            AppWindowToken wtoken = mFinishedStarting.remove(N-1);
-
-                            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
-                                    "Finished starting " + wtoken
-                                    + ": startingWindow=" + wtoken.startingWindow
-                                    + " startingView=" + wtoken.startingView);
-
-                            if (wtoken.startingWindow == null) {
-                                continue;
-                            }
-
-                            view = wtoken.startingView;
-                            token = wtoken.token;
-                            wtoken.startingData = null;
-                            wtoken.startingView = null;
-                            wtoken.startingWindow = null;
-                            wtoken.startingDisplayed = false;
-                        }
-
-                        try {
-                            mPolicy.removeStartingWindow(token, view);
-                        } catch (Exception e) {
-                            Slog.w(TAG_WM, "Exception when removing starting window", e);
-                        }
-                    }
-                } break;
-
                 case WINDOW_FREEZE_TIMEOUT: {
                     // TODO(multidisplay): Can non-default displays rotate?
                     synchronized (mWindowMap) {
@@ -7348,21 +7198,6 @@
     private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
         mRoot.dumpTokens(pw, dumpAll);
-        if (!mFinishedStarting.isEmpty()) {
-            pw.println();
-            pw.println("  Finishing start of application tokens:");
-            for (int i=mFinishedStarting.size()-1; i>=0; i--) {
-                WindowToken token = mFinishedStarting.get(i);
-                pw.print("  Finished Starting #"); pw.print(i);
-                        pw.print(' '); pw.print(token);
-                if (dumpAll) {
-                    pw.println(':');
-                    token.dump(pw, "    ");
-                } else {
-                    pw.println();
-                }
-            }
-        }
         if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
             pw.println();
             if (mOpeningApps.size() > 0) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e5ed18d..19ef44c 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -461,16 +461,7 @@
         mStackClip = STACK_CLIP_BEFORE_ANIM;
         mWin.checkPolicyVisibilityChange();
         mTransformation.clear();
-        if (mDrawState == HAS_DRAWN
-                && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
-                && mWin.mAppToken != null
-                && mWin.mAppToken.firstWindowDrawn
-                && mWin.mAppToken.startingData != null) {
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
-                    + mWin.mToken + ": first real window done animating");
-            mService.mFinishedStarting.add(mWin.mAppToken);
-            mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
-        } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
+        if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
             // Upon completion of a not-visible to visible status bar animation a relayout is
             // required.
             if (displayContent != null) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 1aabd5e..4df1001 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -441,8 +441,9 @@
             wtoken.deferClearAllDrawn = false;
             // Ensure that apps that are mid-starting are also scheduled to have their
             // starting windows removed after the animation is complete
-            if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
-                mService.scheduleRemoveStartingWindowLocked(wtoken);
+            if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit
+                    && wtoken.getController() != null) {
+                wtoken.getController().removeStartingWindow();
             }
             mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
 
diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp
index c54d732..4d85d9a 100644
--- a/services/core/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp
@@ -17,24 +17,25 @@
 #define LOG_NDEBUG 0
 
 #define LOG_TAG "VpnJni"
-#include <cutils/log.h>
-#include "netutils/ifc.h"
 
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
 #include <errno.h>
 #include <fcntl.h>
-
 #include <linux/if.h>
 #include <linux/if_tun.h>
 #include <linux/route.h>
 #include <linux/ipv6_route.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+
+#include "netutils/ifc.h"
 
 #include "jni.h"
 #include "JNIHelp.h"
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index cf7f1cb..2fd0603 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -103,16 +103,15 @@
         state.flashMode = Flash::NONE;
     } else {
         // Only set non-brightness settings when not in low-persistence mode
-        state.color = colorARGB;
         state.flashMode = flash;
         state.flashOnMs = onMS;
         state.flashOffMs = offMS;
     }
 
+    state.color = colorARGB;
     state.brightnessMode = brightness;
 
     Status status;
-
     {
         ALOGD_IF_SLOW(50, "Excessive delay setting light");
         Return<Status> ret = gLight->setLight(type, state);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 09886db..5046265 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -59,6 +59,12 @@
 static jmethodID method_reportMeasurementData;
 static jmethodID method_reportNavigationMessages;
 
+/*
+ * Save a pointer to JavaVm to attach/detach threads executing
+ * callback methods that need to make JNI calls.
+ */
+static JavaVM* sJvm;
+
 using android::OK;
 using android::sp;
 using android::status_t;
@@ -216,6 +222,62 @@
     }
 }
 
+class ScopedJniThreadAttach {
+public:
+    ScopedJniThreadAttach() {
+        /*
+         * attachResult will also be JNI_OK if the thead was already attached to
+         * JNI before the call to AttachCurrentThread().
+         */
+        jint attachResult = sJvm->AttachCurrentThread(&mEnv, nullptr);
+        LOG_ALWAYS_FATAL_IF(attachResult != JNI_OK, "Unable to attach thread. Error %d",
+                            attachResult);
+    }
+
+    ~ScopedJniThreadAttach() {
+        jint detachResult = sJvm->DetachCurrentThread();
+        /*
+         * Return if the thread was already detached. Log error for any other
+         * failure.
+         */
+        if (detachResult == JNI_EDETACHED) {
+            return;
+        }
+
+        LOG_ALWAYS_FATAL_IF(detachResult != JNI_OK, "Unable to detach thread. Error %d",
+                            detachResult);
+    }
+
+    JNIEnv* getEnv() {
+        /*
+         * Checking validity of mEnv in case the thread was detached elsewhere.
+         */
+        LOG_ALWAYS_FATAL_IF(AndroidRuntime::getJNIEnv() != mEnv);
+        return mEnv;
+    }
+
+private:
+    JNIEnv* mEnv = nullptr;
+};
+
+thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
+
+static JNIEnv* getJniEnv() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+    /*
+     * If env is nullptr, the thread is not already attached to
+     * JNI. It is attached below and the destructor for ScopedJniThreadAttach
+     * will detach it on thread exit.
+     */
+    if (env == nullptr) {
+        tJniThreadAttacher.reset(new ScopedJniThreadAttach());
+        env = tJniThreadAttacher->getEnv();
+    }
+
+    return env;
+}
+
 /*
  * GnssCallback class implements the callback methods for IGnss interface.
  */
@@ -247,7 +309,7 @@
 
 Return<void> GnssCallback::gnssLocationCb(
         const ::android::hardware::gnss::V1_0::GnssLocation& location) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj,
                         method_reportLocation,
                         location.gnssLocationFlags,
@@ -263,14 +325,14 @@
 }
 
 Return<void> GnssCallback::gnssStatusCb(const IGnssCallback::GnssStatusValue status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_reportStatus, status);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
 }
 
 Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
 
     sGnssSvListSize = svStatus.numSvs;
     if (sGnssSvListSize > static_cast<uint32_t>(
@@ -292,7 +354,7 @@
 
 Return<void> GnssCallback::gnssNmeaCb(
     int64_t timestamp, const ::android::hardware::hidl_string& nmea) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     /*
      * The Java code will call back to read these values.
      * We do this to avoid creating unnecessary String objects.
@@ -308,7 +370,7 @@
 Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
     ALOGD("%s: %du\n", __func__, capabilities);
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
@@ -325,7 +387,7 @@
 }
 
 Return<void> GnssCallback::gnssRequestTimeCb() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
@@ -334,7 +396,7 @@
 Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) {
     ALOGD("%s: yearOfHw=%d\n", __func__, info.yearOfHw);
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
                         info.yearOfHw);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -350,7 +412,7 @@
  * interface.
  */
 Return<void> GnssXtraCallback::downloadRequestCb() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
@@ -385,7 +447,7 @@
         const android::hardware::gnss::V1_0::GnssLocation& location,
         GeofenceTransition transition,
         hardware::gnss::V1_0::GnssUtcTime timestamp) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
 
     env->CallVoidMethod(mCallbacksObj,
                         method_reportGeofenceTransition,
@@ -408,7 +470,7 @@
 Return<void> GnssGeofenceCallback::gnssGeofenceStatusCb(
         GeofenceAvailability status,
         const android::hardware::gnss::V1_0::GnssLocation& location) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj,
                         method_reportGeofenceStatus,
                         status,
@@ -426,7 +488,7 @@
 
 Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId,
                                                     GeofenceStatus status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
         ALOGE("%s: Error in adding a Geofence: %d\n", __func__, status);
     }
@@ -441,7 +503,7 @@
 
 Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId,
                                                        GeofenceStatus status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
         ALOGE("%s: Error in removing a Geofence: %d\n", __func__, status);
     }
@@ -455,7 +517,7 @@
 
 Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId,
                                                       GeofenceStatus status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
         ALOGE("%s: Error in pausing Geofence: %d\n", __func__, status);
     }
@@ -469,7 +531,7 @@
 
 Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId,
                                                        GeofenceStatus status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
         ALOGE("%s: Error in resuming Geofence: %d\n", __func__, status);
     }
@@ -496,7 +558,7 @@
 
 Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
         const IGnssNavigationMessageCallback::GnssNavigationMessage& message) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
 
     size_t dataLength = message.data.size();
 
@@ -545,7 +607,7 @@
 
 Return<void> GnssMeasurementCallback::GnssMeasurementCb(
         const IGnssMeasurementCallback::GnssData& data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
 
     jobject clock;
     jobjectArray measurementArray;
@@ -700,7 +762,7 @@
 
 Return<void> GnssNiCallback::niNotifyCb(
         const IGnssNiCallback::GnssNiNotification& notification) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
     jstring text = env->NewStringUTF(notification.notificationMessage.c_str());
 
@@ -742,7 +804,7 @@
 
 Return<void> AGnssCallback::agnssStatusIpV6Cb(
         const IAGnssCallback::AGnssStatusIpV6& agps_status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     jbyteArray byteArray = NULL;
     bool isSupported = false;
 
@@ -778,7 +840,7 @@
 
 Return<void> AGnssCallback::agnssStatusIpV4Cb(
         const IAGnssCallback::AGnssStatusIpV4& agps_status) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     jbyteArray byteArray = NULL;
 
     uint32_t ipAddr = agps_status.ipV4Addr;
@@ -813,7 +875,7 @@
         return NULL;
     }
 
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     jbyteArray byteArray = env->NewByteArray(4);
     if (byteArray == NULL) {
         ALOGE("Unable to allocate byte array for IPv4 address");
@@ -837,14 +899,14 @@
 };
 
 Return<void> AGnssRilCallback::requestSetIdCb(IAGnssRilCallback::ID setIdFlag) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_requestSetID, setIdFlag);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
 }
 
 Return<void> AGnssRilCallback::requestRefLocCb() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    JNIEnv* env = getJniEnv();
     env->CallVoidMethod(mCallbacksObj, method_requestRefLocation);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
@@ -885,6 +947,14 @@
             "reportNavigationMessage",
             "(Landroid/location/GnssNavigationMessage;)V");
 
+    /*
+     * Save a pointer to JVM.
+     */
+    jint jvmStatus = env->GetJavaVM(&sJvm);
+    if (jvmStatus != JNI_OK) {
+        LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
+    }
+
     // TODO(b/31632518)
     gnssHal = IGnss::getService("gnss");
     if (gnssHal != nullptr) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9f66062..2e5b687 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -10097,6 +10097,7 @@
                 .setSmallIcon(R.drawable.ic_qs_network_logging)
                 .setContentTitle(mContext.getString(R.string.network_logging_notification_title))
                 .setContentText(mContext.getString(R.string.network_logging_notification_text))
+                .setTicker(mContext.getString(R.string.network_logging_notification_title))
                 .setShowWhen(true)
                 .setContentIntent(pendingIntent)
                 .build();
diff --git a/services/tests/notification/AndroidManifest.xml b/services/tests/notification/AndroidManifest.xml
index 087806e..1ed8ed0 100644
--- a/services/tests/notification/AndroidManifest.xml
+++ b/services/tests/notification/AndroidManifest.xml
@@ -18,7 +18,10 @@
         package="com.android.frameworks.tests.notification">
 
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index ef61ec2..40938fd 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.notification;
 
+import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
@@ -29,24 +30,29 @@
 import static org.mockito.Mockito.when;
 
 import android.app.INotificationManager;
-import android.app.IOnNotificationChannelCreatedListener;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
+import android.content.pm.ParceledListSlice;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
+import android.support.test.annotation.UiThreadTest;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import com.android.server.lights.Light;
+import com.android.server.lights.LightsManager;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -58,6 +64,7 @@
     private IPackageManager mPackageManager = mock(IPackageManager.class);
 
     @Before
+    @UiThreadTest
     public void setUp() throws Exception {
         final Context context = InstrumentationRegistry.getTargetContext();
         mNotificationManagerService = new NotificationManagerService(context);
@@ -67,37 +74,32 @@
         applicationInfo.uid = Binder.getCallingUid();
         when(mPackageManager.getApplicationInfo(any(), anyInt(), anyInt()))
                 .thenReturn(applicationInfo);
-        mNotificationManagerService.setPackageManager(mPackageManager);
-        mNotificationManagerService.setHandler(new Handler(context.getMainLooper()));
+        final LightsManager mockLightsManager = mock(LightsManager.class);
+        when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
+        mNotificationManagerService.init(mPackageManager, mockLightsManager);
 
         // Tests call directly into the Binder.
         mBinderService = mNotificationManagerService.getBinderService();
     }
 
     @Test
-    public void testCreateNotificationChannel_SuccessCallsListener() throws Exception {
+    @UiThreadTest
+    public void testCreateNotificationChannels_SingleChannel() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
-        mNotificationManagerService.setRankingHelper(mock(RankingHelper.class));
-        final CountDownLatch latch = new CountDownLatch(1);
-        mBinderService.createNotificationChannel("test_pkg", channel,
-                new IOnNotificationChannelCreatedListener.Stub() {
-                    @Override public void onNotificationChannelCreated(
-                            NotificationChannel channel) {
-                        latch.countDown();
-                    }});
-        latch.await();
+        mBinderService.createNotificationChannels("test_pkg",
+                new ParceledListSlice(Arrays.asList(channel)));
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel("test_pkg", "id");
+        assertTrue(createdChannel != null);
     }
 
     @Test
-    public void testCreateNotificationChannel_FailureDoesNotCallListener() throws Exception {
+    @UiThreadTest
+    public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
         try {
-            mBinderService.createNotificationChannel("test_pkg", null,
-                    new IOnNotificationChannelCreatedListener.Stub() {
-                        @Override public void onNotificationChannelCreated(
-                                NotificationChannel channel) {
-                            fail("Listener was triggered from failure.");
-                        }});
+            mBinderService.createNotificationChannels("test_pkg",
+                    new ParceledListSlice(Arrays.asList(null)));
             fail("Exception should be thrown immediately.");
         } catch (NullPointerException e) {
             // pass
@@ -105,6 +107,54 @@
     }
 
     @Test
+    @UiThreadTest
+    public void testCreateNotificationChannels_TwoChannels() throws Exception {
+        final NotificationChannel channel1 =
+                new NotificationChannel("id1", "name", NotificationManager.IMPORTANCE_DEFAULT);
+        final NotificationChannel channel2 =
+                new NotificationChannel("id2", "name", NotificationManager.IMPORTANCE_DEFAULT);
+        mBinderService.createNotificationChannels("test_pkg",
+                new ParceledListSlice(Arrays.asList(channel1, channel2)));
+        assertTrue(mBinderService.getNotificationChannel("test_pkg", "id1") != null);
+        assertTrue(mBinderService.getNotificationChannel("test_pkg", "id2") != null);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
+            throws Exception {
+        final NotificationChannel channel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+        mBinderService.createNotificationChannels("test_pkg",
+                new ParceledListSlice(Arrays.asList(channel)));
+
+        // Recreating the channel doesn't throw, but ignores importance.
+        final NotificationChannel dupeChannel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+        mBinderService.createNotificationChannels("test_pkg",
+                new ParceledListSlice(Arrays.asList(dupeChannel)));
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel("test_pkg", "id");
+        assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
+            throws Exception {
+        final NotificationChannel channel1 =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+        final NotificationChannel channel2 =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+        mBinderService.createNotificationChannels("test_pkg",
+                new ParceledListSlice(Arrays.asList(channel1, channel2)));
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel("test_pkg", "id");
+        assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
+    }
+
+    @Test
+    @UiThreadTest
     public void testBlockedNotifications_suspended() throws Exception {
         NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
@@ -120,6 +170,7 @@
     }
 
     @Test
+    @UiThreadTest
     public void testBlockedNotifications_blockedChannel() throws Exception {
         NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
@@ -136,6 +187,7 @@
     }
 
     @Test
+    @UiThreadTest
     public void testBlockedNotifications_blockedApp() throws Exception {
         NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 9c5c672..1189dae 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -23,6 +23,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
@@ -61,6 +62,7 @@
 import android.net.ScoredNetwork;
 import android.net.WifiKey;
 import android.net.wifi.WifiConfiguration;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
@@ -261,7 +263,7 @@
 
     @Test
     public void testUpdateScores_notActiveScorer() {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+        bindToScorer(false /*callerIsScorer*/);
 
         try {
             mNetworkScoreService.updateScores(new ScoredNetwork[0]);
@@ -273,7 +275,7 @@
 
     @Test
     public void testUpdateScores_oneRegisteredCache() throws RemoteException {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+        bindToScorer(true /*callerIsScorer*/);
 
         mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
                 mNetworkScoreCache, CACHE_FILTER_NONE);
@@ -288,7 +290,7 @@
 
     @Test
     public void testUpdateScores_twoRegisteredCaches() throws RemoteException {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+        bindToScorer(true /*callerIsScorer*/);
 
         mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
                 mNetworkScoreCache, CACHE_FILTER_NONE);
@@ -322,8 +324,8 @@
     }
 
     @Test
-    public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+    public void testClearScores_notActiveScorer_noRequestNetworkScoresPermission() {
+        bindToScorer(false /*callerIsScorer*/);
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
             .thenReturn(PackageManager.PERMISSION_DENIED);
         try {
@@ -335,8 +337,8 @@
     }
 
     @Test
-    public void testClearScores_activeScorer_noBroadcastNetworkPermission() {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+    public void testClearScores_activeScorer_noRequestNetworkScoresPermission() {
+        bindToScorer(true /*callerIsScorer*/);
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
             .thenReturn(PackageManager.PERMISSION_DENIED);
 
@@ -345,7 +347,7 @@
 
     @Test
     public void testClearScores_activeScorer() throws RemoteException {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true);
+        bindToScorer(true /*callerIsScorer*/);
 
         mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
                 CACHE_FILTER_NONE);
@@ -355,9 +357,9 @@
     }
 
     @Test
-    public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission()
+    public void testClearScores_notActiveScorer_hasRequestNetworkScoresPermission()
             throws RemoteException {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+        bindToScorer(false /*callerIsScorer*/);
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
 
@@ -382,8 +384,8 @@
     }
 
     @Test
-    public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() {
-        when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false);
+    public void testDisableScoring_notActiveScorer_noRequestNetworkScoresPermission() {
+        bindToScorer(false /*callerIsScorer*/);
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                 .thenReturn(PackageManager.PERMISSION_DENIED);
 
@@ -396,7 +398,7 @@
     }
 
     @Test
-    public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() {
+    public void testRegisterNetworkScoreCache_noRequestNetworkScoresPermission() {
         doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                 eq(permission.REQUEST_NETWORK_SCORES), anyString());
 
@@ -410,7 +412,7 @@
     }
 
     @Test
-    public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() {
+    public void testUnregisterNetworkScoreCache_noRequestNetworkScoresPermission() {
         doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission(
                 eq(permission.REQUEST_NETWORK_SCORES), anyString());
 
@@ -448,6 +450,42 @@
         assertFalse(stringWriter.toString().isEmpty());
     }
 
+    @Test
+    public void testIsCallerActiveScorer_noBoundService() throws Exception {
+        mNetworkScoreService.systemRunning();
+
+        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+    }
+
+    @Test
+    public void testIsCallerActiveScorer_boundServiceIsNotCaller() throws Exception {
+        bindToScorer(false /*callerIsScorer*/);
+
+        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+    }
+
+    @Test
+    public void testIsCallerActiveScorer_boundServiceIsCaller() throws Exception {
+        bindToScorer(true /*callerIsScorer*/);
+
+        assertTrue(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+    }
+
+    @Test
+    public void testGetActiveScorerPackage_notActive() throws Exception {
+        mNetworkScoreService.systemRunning();
+
+        assertNull(mNetworkScoreService.getActiveScorerPackage());
+    }
+
+    @Test
+    public void testGetActiveScorerPackage_active() throws Exception {
+        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
+        mNetworkScoreService.systemRunning();
+
+        assertEquals(NEW_SCORER.packageName, mNetworkScoreService.getActiveScorerPackage());
+    }
+
     // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
     private void injectProvider() {
         final ComponentName componentName = new ComponentName(NEW_SCORER.packageName,
@@ -467,4 +505,14 @@
         });
         mNetworkScoreService.systemRunning();
     }
+
+    private void bindToScorer(boolean callerIsScorer) {
+        final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0;
+        NetworkScorerAppData appData = new NetworkScorerAppData(NEW_SCORER.packageName,
+                callingUid, NEW_SCORER.recommendationServiceClassName);
+        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
+        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
+                isA(UserHandle.class))).thenReturn(true);
+        mNetworkScoreService.systemRunning();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index d392459..182f045 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2289,6 +2289,11 @@
         setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid);
         mContext.packageName = admin1.getPackageName();
 
+        final ComponentName adminDifferentPackage =
+                new ComponentName("another.package", "whatever.random.class");
+        final int ANOTHER_UID = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, 948);
+        setUpPackageManagerForFakeAdmin(adminDifferentPackage, ANOTHER_UID, admin2);
+
         // COMP mode is allowed.
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
 
@@ -2304,12 +2309,66 @@
                 .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
 
+        // But another app should not
+        mContext.binder.callingUid = ANOTHER_UID;
+        mContext.packageName = adminDifferentPackage.getPackageName();
+        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+
         // The DO should not be allowed to initiate provisioning if the restriction is set by
         // another entity.
         when(mContext.userManager.getUserRestrictionSource(
                 eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
                 eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
                 .thenReturn(UserManager.RESTRICTION_SOURCE_SYSTEM);
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        mContext.packageName = admin1.getPackageName();
+        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+
+        mContext.binder.callingUid = ANOTHER_UID;
+        mContext.packageName = adminDifferentPackage.getPackageName();
+        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+    }
+
+    public void testIsProvisioningAllowed_nonSplitUser_comp() throws Exception {
+        setDeviceOwner();
+        setup_nonSplitUser_afterDeviceSetup_primaryUser();
+        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
+
+        final ComponentName adminDifferentPackage =
+                new ComponentName("another.package", "whatever.class");
+        final int ANOTHER_UID = UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE, 948);
+        setUpPackageManagerForFakeAdmin(adminDifferentPackage, ANOTHER_UID, admin2);
+
+        final int MANAGED_PROFILE_USER_ID = 18;
+        final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 1308);
+        addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
+
+        when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
+                false /* we can't remove a managed profile */)).thenReturn(false);
+        when(mContext.userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
+                true)).thenReturn(true);
+
+        // We can delete the managed profile to create a new one, so provisioning is allowed.
+        mContext.packageName = admin1.getPackageName();
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+
+        mContext.packageName = adminDifferentPackage.getPackageName();
+        mContext.binder.callingUid = ANOTHER_UID;
+        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+
+        when(mContext.userManager.hasUserRestriction(
+                eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE),
+                eq(UserHandle.of(DpmMockContext.CALLER_USER_HANDLE))))
+                .thenReturn(true);
+
+        // Now, we can't remove the profile any more to create a new one.
+        mContext.packageName = admin1.getPackageName();
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
+
+        mContext.packageName = adminDifferentPackage.getPackageName();
+        mContext.binder.callingUid = ANOTHER_UID;
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 10ca902..228b8e0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -1403,7 +1403,7 @@
     protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
             Icon icon, Intent intent, int rank) {
         final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, id)
-                .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy"))
+                .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
                 .setShortLabel(title)
                 .setRank(rank)
                 .setIntent(intent);
@@ -1432,7 +1432,7 @@
     protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
             Icon icon, Intent[] intents, int rank) {
         final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, id)
-                .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy"))
+                .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
                 .setShortLabel(title)
                 .setRank(rank)
                 .setIntents(intents);
@@ -1455,7 +1455,7 @@
     protected ShortcutInfo makeShortcutWithExtras(String id, Intent intent,
             PersistableBundle extras) {
         final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, id)
-                .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy"))
+                .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
                 .setShortLabel("title-" + id)
                 .setExtras(extras)
                 .setIntent(intent);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index fbf0ed2..bcd72fc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -38,6 +38,7 @@
 import android.os.UserHandle;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.frameworks.servicestests.R;
@@ -227,8 +228,9 @@
 
     private void assertPinItemRequest(PinItemRequest actualRequest) {
         assertNotNull(actualRequest);
-
         assertEquals(PinItemRequest.REQUEST_TYPE_SHORTCUT, actualRequest.getRequestType());
+
+        Log.i(TAG, "Requested shortcut: " + actualRequest.getShortcutInfo().toInsecureString());
     }
 
     /**
@@ -243,9 +245,16 @@
         final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
-            ShortcutInfo s1 = makeShortcutWithIcon("s1", res32x32);
+            /// Create a shortcut with no target activity.
+            final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, "s1")
+                    .setShortLabel("Title-" + "s1")
+                    .setIcon(res32x32)
+                    .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class));
+            final ShortcutInfo s = b.build();
 
-            assertTrue(mManager.requestPinShortcut(s1,
+            assertNull(s.getActivity());
+
+            assertTrue(mManager.requestPinShortcut(s,
                     resultIntent == null ? null : resultIntent.getIntentSender()));
 
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
@@ -271,6 +280,7 @@
             assertWith(request.getShortcutInfo())
                     .haveIds("s1")
                     .areAllOrphan()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, MAIN_ACTIVITY_CLASS))
                     .areAllWithNoIntent();
 
             assertAllHaveIcon(list(request.getShortcutInfo()));
@@ -295,6 +305,7 @@
                     .areAllNotDynamic()
                     .areAllEnabled()
                     .areAllPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, MAIN_ACTIVITY_CLASS))
                     .areAllWithIntent();
         });
     }
@@ -310,6 +321,145 @@
         checkRequestPinShortcut(resultIntent);
     }
 
+    public void testRequestPinShortcut_explicitTargetActivity() {
+        setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
+        setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            ShortcutInfo s1 = makeShortcutWithActivity("s1",
+                    new ComponentName(CALLING_PACKAGE_1, "different_activity"));
+
+            assertTrue(mManager.requestPinShortcut(s1, null));
+
+            verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
+
+            // Shortcut shouldn't be registered yet.
+            assertWith(getCallerShortcuts())
+                    .isEmpty();
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // Check the intent passed to startActivityAsUser().
+            final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+
+            assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
+
+            // Check the request object.
+            final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
+
+            assertPinItemRequest(request);
+
+            assertWith(request.getShortcutInfo())
+                    .haveIds("s1")
+                    .areAllOrphan()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "different_activity"))
+                    .areAllWithNoIntent();
+
+            // Accept the request.
+            assertForLauncherCallbackNoThrow(mLauncherApps,
+                    () -> assertTrue(request.accept()))
+                    .assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_P0)
+                    .haveIds("s1");
+        });
+
+        verify(mServiceContext, times(1)).sendIntentSender(eq(null));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("s1")
+                    .areAllNotDynamic()
+                    .areAllEnabled()
+                    .areAllPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "different_activity"))
+                    .areAllWithIntent();
+        });
+    }
+
+    public void testRequestPinShortcut_wrongTargetActivity() {
+        setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            // Create dynamic shortcut
+            ShortcutInfo s1 = makeShortcutWithActivity("s1",
+                    new ComponentName("wrong_package", "different_activity"));
+
+            assertExpectException(IllegalStateException.class, "not belong to package", () -> {
+                assertTrue(mManager.requestPinShortcut(s1, /* resultIntent=*/ null));
+            });
+
+            verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
+            verify(mServiceContext, times(0)).startActivityAsUser(
+                    any(Intent.class), any(UserHandle.class));
+        });
+    }
+
+    public void testRequestPinShortcut_noTargetActivity_noMainActivity() {
+        setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
+        setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            /// Create a shortcut with no target activity.
+            final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, "s1")
+                    .setShortLabel("Title-" + "s1")
+                    .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class));
+            final ShortcutInfo s = b.build();
+
+            assertNull(s.getActivity());
+
+            // Caller has no main activity.
+            mMainActivityFetcher = (packageName, userId) -> null;
+
+            assertTrue(mManager.requestPinShortcut(s, null));
+
+            verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
+
+            // Shortcut shouldn't be registered yet.
+            assertWith(getCallerShortcuts())
+                    .isEmpty();
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // Check the intent passed to startActivityAsUser().
+            final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+
+            assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
+
+            // Check the request object.
+            final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
+
+            assertPinItemRequest(request);
+
+            assertWith(request.getShortcutInfo())
+                    .haveIds("s1")
+                    .areAllOrphan()
+                    .areAllWithNoActivity() // Activity is not set; expected.
+                    .areAllWithNoIntent();
+
+            // Accept the request.
+            assertForLauncherCallbackNoThrow(mLauncherApps,
+                    () -> assertTrue(request.accept()))
+                    .assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_P0)
+                    .haveIds("s1");
+        });
+
+        verify(mServiceContext, times(1)).sendIntentSender(eq(null));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("s1")
+                    .areAllNotDynamic()
+                    .areAllEnabled()
+                    .areAllPinned()
+                    .areAllWithNoActivity() // Activity is not set; expected.
+                    .areAllWithIntent();
+        });
+
+    }
+
     public void testRequestPinShortcut_dynamicExists() {
         setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
 
@@ -328,6 +478,7 @@
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
                     .areAllDynamic()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllNotPinned();
         });
 
@@ -348,6 +499,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
             assertAllHaveIcon(list(request.getShortcutInfo()));
@@ -361,6 +513,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
         });
     }
@@ -379,6 +532,8 @@
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
                     .areAllManifest()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllNotPinned();
         });
 
@@ -399,6 +554,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllWithNoIntent();
 
             assertAllHaveIcon(list(request.getShortcutInfo()));
@@ -412,6 +569,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllPinned();
         });
     }
@@ -431,6 +590,7 @@
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
                     .areAllDynamic()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
 
             assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("s1"),
@@ -456,6 +616,8 @@
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
                     .areAllManifest()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllPinned();
 
             assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("ms1"),
@@ -483,6 +645,7 @@
                     .haveIds("s1")
                     .areAllNotDynamic()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
 
             assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("s1"),
@@ -511,6 +674,7 @@
                     .haveIds("s1")
                     .areAllNotDynamic()
                     .areAllDisabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
 
             assertExpectException(IllegalArgumentException.class, "exists but disabled", () -> {
@@ -541,6 +705,8 @@
                     .haveIds("ms1")
                     .areAllNotManifest()
                     .areAllDisabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllPinned();
 
             assertExpectException(IllegalArgumentException.class, "exists but disabled", () -> {
@@ -570,6 +736,7 @@
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
                     .areAllDynamic()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
 
             // The shortcut is already pinned, but not by the current launcher, so it'll still
@@ -597,6 +764,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned() // Note it's not pinned by this launcher.
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
             // Accept the request.
@@ -608,6 +776,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
         });
     }
@@ -629,6 +798,8 @@
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
                     .areAllManifest()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllPinned();
 
             // The shortcut is already pinned, but not by the current launcher, so it'll still
@@ -656,6 +827,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllNotPinned() // Note it's not pinned by this launcher.
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllWithNoIntent();
 
             // Accept the request.
@@ -667,6 +840,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllPinned();
         });
     }
@@ -710,6 +885,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
             // Accept the request.
@@ -719,6 +895,7 @@
                     .haveIds("s1", "s2")
                     .areAllDynamic()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
         });
 
@@ -727,6 +904,7 @@
                     .haveIds("s1", "s2")
                     .areAllDynamic()
                     .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllPinned();
         });
     }
@@ -752,6 +930,7 @@
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
                     .areAllDynamic()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllNotPinned();
         });
 
@@ -772,6 +951,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
             assertAllHaveIcon(list(request.getShortcutInfo()));
@@ -786,6 +966,7 @@
                     .areAllDynamic()
                     .areAllEnabled()
                     .areAllPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .forShortcutWithId("s1", (si) -> {
                         // Still the original title.
                         assertEquals("Title-s1", si.getShortLabel());
@@ -810,6 +991,8 @@
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
                     .areAllManifest()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllNotPinned();
         });
 
@@ -830,6 +1013,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllWithNoIntent();
 
             assertAllHaveIcon(list(request.getShortcutInfo()));
@@ -844,6 +1029,8 @@
                     .areAllManifest()
                     .areAllEnabled()
                     .areAllPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .forShortcutWithId("ms1", (si) -> {
                         // Still the original title.
                         // Title should be something like:
@@ -893,6 +1080,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
             // Accept the request -> should fail.
@@ -950,9 +1138,9 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
-            // Accept the request -> should fail.
             assertTrue(request.accept());
         });
 
@@ -1004,6 +1192,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllWithNoIntent();
 
             // Accept the request -> should fail.
@@ -1059,10 +1249,11 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllWithNoIntent();
 
 
-            // Accept the request -> should fail.
             assertTrue(request.accept());
         });
 
@@ -1071,6 +1262,9 @@
                     .haveIds("ms1")
                     .areAllMutable() // Note it's no longer immutable.
                     .areAllFloating()
+
+                    // Note it's the activity from makeShortcutWithShortLabel().
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .forShortcutWithId("ms1", si -> {
                         assertEquals("new", si.getShortLabel());
                     });
@@ -1104,6 +1298,7 @@
             mManager.disableShortcuts(list("s1"));
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllDisabled();
         });
 
@@ -1125,6 +1320,7 @@
                     .haveIds("s1")
                     .areAllDynamic()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllWithNoIntent();
 
             // Accept the request -> should fail.
@@ -1144,6 +1340,7 @@
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
                     .areAllDisabled();
         });
     }
@@ -1174,6 +1371,8 @@
             publishManifestShortcutsAsCaller(R.xml.shortcut_0);
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllDisabled();
         });
 
@@ -1195,6 +1394,8 @@
                     .haveIds("ms1")
                     .areAllManifest()
                     .areAllNotPinned()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllWithNoIntent();
 
             // Accept the request -> should fail.
@@ -1214,6 +1415,8 @@
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
                     .areAllDisabled();
         });
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 1853a65..c4fd722 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,29 +16,6 @@
 
 package com.android.server.wm;
 
-import com.android.internal.policy.IKeyguardDismissCallback;
-import com.android.internal.policy.IShortcutService;
-import com.android.server.input.InputManagerService;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.WindowManagerPolicy;
-import android.view.animation.Animation;
-
-import java.io.PrintWriter;
-
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
@@ -62,8 +39,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
-import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
@@ -81,9 +58,30 @@
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-
 import static org.mockito.Mockito.mock;
 
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.animation.Animation;
+
+import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.internal.policy.IShortcutService;
+import com.android.server.input.InputManagerService;
+
+import java.io.PrintWriter;
+
 class TestWindowManagerPolicy implements WindowManagerPolicy {
     private static final String TAG = "TestWindowManagerPolicy";
 
@@ -308,14 +306,14 @@
     }
 
     @Override
-    public View addStartingWindow(IBinder appToken, String packageName, int theme,
+    public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
             CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
             int logo, int windowFlags, Configuration overrideConfig) {
         return null;
     }
 
     @Override
-    public void removeStartingWindow(IBinder appToken, View window) {
+    public void removeSplashScreen(IBinder appToken, StartingSurface surface) {
 
     }
 
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index a664f21..ea45bd1 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -925,7 +925,7 @@
         }
 
         public ShortcutListAsserter areAllWithActivity(ComponentName activity) {
-            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.getActivity().equals(activity)));
+            forAllShortcuts(s -> assertEquals("id=" + s.getId(), activity, s.getActivity()));
             return this;
         }
 
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index c69b7c2..b20384d 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -115,6 +115,13 @@
      */
     public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
 
+    /**
+     * Extra key used to indicate the time (in millis) when the last outgoing emergency call was
+     * made.  This is used to identify potential emergency callbacks.
+     */
+    public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
+            "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
+
     public static class Details {
 
         /** Call can currently be put on hold or unheld. */
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 85584d3..4445a22 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -51,4 +51,8 @@
             view.dispatchDetachedFromWindow();
         }
     }
+
+    public static ViewRootImpl getRootView(View view) {
+        return view.mAttachInfo != null ? view.mAttachInfo.mViewRootImpl : null;
+    }
 }
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java
similarity index 68%
copy from core/java/android/service/autofill/IAutoFillCallback.aidl
copy to tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java
index d6d4f39..0e15b97 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package android.service.autofill;
-
-import java.util.List;
+package android.view;
 
 /**
- * @hide
+ * Accessor to allow layoutlib to call {@link ViewRootImpl#dispatchApplyInsets} directly.
  */
-oneway interface IAutoFillCallback {
-    void autofill(in List values);
-    void showError(String message);
+public class ViewRootImpl_Accessor {
+    public static void dispatchApplyInsets(ViewRootImpl viewRoot, View host) {
+        viewRoot.dispatchApplyInsets(host);
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index 726ff22..2fe3ed5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -38,7 +38,10 @@
 import android.graphics.drawable.Drawable;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
+import android.view.AttachInfo_Accessor;
 import android.view.View;
+import android.view.ViewRootImpl;
+import android.view.ViewRootImpl_Accessor;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
@@ -302,6 +305,17 @@
         return Bridge.getResourceId(ResourceType.ID, ID_PREFIX + name);
     }
 
+    @Override
+    public void requestFitSystemWindows() {
+        // The framework call would usually bubble up to ViewRootImpl but, in layoutlib, Layout will
+        // act as view root for most purposes. That way, we can also save going through the Handler
+        // to dispatch the new applied insets.
+        ViewRootImpl root = AttachInfo_Accessor.getRootView(this);
+        if (root != null) {
+            ViewRootImpl_Accessor.dispatchApplyInsets(root, this);
+        }
+    }
+
     /**
      * A helper class to help initialize the Layout.
      */
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java
new file mode 100644
index 0000000..36e5c26
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.test.myapplication.widgets;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.WindowInsets;
+import android.widget.TextView;
+
+public class InsetsWidget extends TextView {
+    public static boolean sApplyInsetsCalled = false;
+
+    public InsetsWidget(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        requestApplyInsets();
+    }
+
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        sApplyInsetsCalled = true;
+        return super.onApplyWindowInsets(insets);
+    }
+}
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/insets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/insets.xml
new file mode 100644
index 0000000..ff06d79
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/insets.xml
@@ -0,0 +1,12 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:padding="16dp"
+              android:orientation="horizontal"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content">
+
+    <com.android.layoutlib.test.myapplication.widgets.InsetsWidget
+        android:text="Hello world"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text1"/>
+</LinearLayout>
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index c813a12..7a436eb 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -63,6 +63,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -87,6 +88,7 @@
 import com.google.android.collect.Lists;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -434,6 +436,37 @@
         renderAndVerify(params, "simple_activity.png");
     }
 
+    @Test
+    public void testOnApplyInsetsCall()
+            throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
+        // We get the widget via reflection to avoid IntelliJ complaining about the class being
+        // located in the wrong package. (From the Bridge tests point of view, it is)
+        Class insetsWidgetClass = Class.forName("com.android.layoutlib.test.myapplication.widgets" +
+                ".InsetsWidget");
+        Field field = insetsWidgetClass.getDeclaredField("sApplyInsetsCalled");
+        assertFalse((Boolean)field.get(null));
+
+        LayoutPullParser parser = createLayoutPullParser("insets.xml");
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+                layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
+                RenderingMode.NORMAL, 22);
+        try {
+            renderAndVerify(params, "scrolled.png");
+        } catch(AssertionError e) {
+            // In this particular test we do not care about the image similarity.
+            // TODO: Create new render method that allows to not compare images.
+            if (!e.getLocalizedMessage().startsWith("Images differ")) {
+                throw e;
+            }
+        }
+
+        assertTrue((Boolean)field.get(null));
+        field.set(null, false);
+    }
+
     @AfterClass
     public static void tearDown() {
         sLayoutLibLog = null;