Merge "Deprecating secure setting install_non_market_apps"
diff --git a/Android.mk b/Android.mk
index 22323c5..a1e9ed9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -265,8 +265,9 @@
 	core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.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/autofill/IFillCallback.aidl \
+	core/java/android/service/autofill/ISaveCallback.aidl \
 	core/java/android/service/carrier/ICarrierService.aidl \
 	core/java/android/service/carrier/ICarrierMessagingCallback.aidl \
 	core/java/android/service/carrier/ICarrierMessagingService.aidl \
@@ -294,6 +295,10 @@
 	core/java/android/print/IWriteResultCallback.aidl \
 	core/java/android/printservice/IPrintService.aidl \
 	core/java/android/printservice/IPrintServiceClient.aidl \
+	core/java/android/companion/ICompanionDeviceManager.aidl \
+	core/java/android/companion/ICompanionDeviceManagerService.aidl \
+	core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl \
+	core/java/android/companion/IOnAssociateCallback.aidl \
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
 	core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
diff --git a/api/current.txt b/api/current.txt
index eca3c27..7db661b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -118,6 +118,7 @@
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -2688,11 +2689,25 @@
 
 package android.accessibilityservice {
 
+  public final class AccessibilityButtonController {
+    method public boolean isAccessibilityButtonAvailable();
+    method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+    method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback, android.os.Handler);
+    method public void unregisterAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+  }
+
+  public static abstract class AccessibilityButtonController.AccessibilityButtonCallback {
+    ctor public AccessibilityButtonController.AccessibilityButtonCallback();
+    method public void onAvailabilityChanged(android.accessibilityservice.AccessibilityButtonController, boolean);
+    method public void onClicked(android.accessibilityservice.AccessibilityButtonController);
+  }
+
   public abstract class AccessibilityService extends android.app.Service {
     ctor public AccessibilityService();
     method public final void disableSelf();
     method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
     method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2805,6 +2820,7 @@
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+    field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
     field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
     field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
     field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
@@ -5046,14 +5062,19 @@
     ctor public Notification(android.os.Parcel);
     method public android.app.Notification clone();
     method public int describeContents();
+    method public int getBadgeIcon();
     method public java.lang.String getChannel();
     method public java.lang.String getGroup();
     method public android.graphics.drawable.Icon getLargeIcon();
+    method public java.lang.String getShortcutId();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
     method public long getTimeout();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+    field public static final int BADGE_ICON_LARGE = 2; // 0x2
+    field public static final int BADGE_ICON_NONE = 0; // 0x0
+    field public static final int BADGE_ICON_SMALL = 1; // 0x1
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
     field public static final java.lang.String CATEGORY_CALL = "call";
     field public static final java.lang.String CATEGORY_EMAIL = "email";
@@ -5145,7 +5166,7 @@
     field public deprecated int ledARGB;
     field public deprecated int ledOffMS;
     field public deprecated int ledOnMS;
-    field public deprecated int number;
+    field public int number;
     field public deprecated int priority;
     field public android.app.Notification publicVersion;
     field public deprecated android.net.Uri sound;
@@ -5233,6 +5254,7 @@
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
+    method public android.app.Notification.Builder chooseBadgeIcon(int);
     method public android.widget.RemoteViews createBigContentView();
     method public android.widget.RemoteViews createContentView();
     method public android.widget.RemoteViews createHeadsUpContentView();
@@ -5265,13 +5287,14 @@
     method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public deprecated android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
-    method public deprecated android.app.Notification.Builder setNumber(int);
+    method public android.app.Notification.Builder setNumber(int);
     method public android.app.Notification.Builder setOngoing(boolean);
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public deprecated android.app.Notification.Builder setPriority(int);
     method public android.app.Notification.Builder setProgress(int, int, boolean);
     method public android.app.Notification.Builder setPublicVersion(android.app.Notification);
     method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]);
+    method public android.app.Notification.Builder setShortcutId(java.lang.String);
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
@@ -5655,10 +5678,11 @@
   }
 
   public final class RemoteAction implements android.os.Parcelable {
-    ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
+    ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.RemoteAction clone();
     method public int describeContents();
     method public void dump(java.lang.String, java.io.PrintWriter);
+    method public android.app.PendingIntent getActionIntent();
     method public java.lang.CharSequence getContentDescription();
     method public android.graphics.drawable.Icon getIcon();
     method public java.lang.CharSequence getTitle();
@@ -5666,10 +5690,6 @@
     field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
   }
 
-  public static abstract interface RemoteAction.OnActionListener {
-    method public abstract void onAction(android.app.RemoteAction);
-  }
-
   public final class RemoteInput implements android.os.Parcelable {
     method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
     method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
@@ -6195,6 +6215,7 @@
     method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
+    method public java.lang.String[] getLockTaskPackages(android.content.ComponentName);
     method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
@@ -7943,6 +7964,65 @@
 
 }
 
+package android.companion {
+
+  public final class AssociationRequest<F extends android.companion.DeviceFilter> 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.companion.AssociationRequest> CREATOR;
+  }
+
+  public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
+    method public android.companion.AssociationRequest<F> build();
+    method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
+    method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
+    method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
+    method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+  }
+
+  public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.companion.BluetoothDeviceFilter> CREATOR;
+  }
+
+  public static final class BluetoothDeviceFilter.Builder {
+    ctor public BluetoothDeviceFilter.Builder();
+    method public android.companion.BluetoothDeviceFilter.Builder addServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+    method public android.companion.BluetoothDeviceFilter build();
+    method public android.companion.BluetoothDeviceFilter.Builder setAddress(java.lang.String);
+    method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+  }
+
+  public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+  }
+
+  public static final class BluetoothLEDeviceFilter.Builder {
+    ctor public BluetoothLEDeviceFilter.Builder();
+    method public android.companion.BluetoothLEDeviceFilter build();
+    method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+    method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+  }
+
+  public final class CompanionDeviceManager {
+    method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+    field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+  }
+
+  public static abstract class CompanionDeviceManager.Callback {
+    ctor public CompanionDeviceManager.Callback();
+    method public abstract void onDeviceFound(android.content.IntentSender);
+    method public abstract void onFailure(java.lang.CharSequence);
+  }
+
+  public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
+  }
+
+}
+
 package android.content {
 
   public abstract class AbstractThreadedSyncAdapter {
@@ -8555,6 +8635,7 @@
     field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
     field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -9092,6 +9173,10 @@
     field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
     field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
     field public static final java.lang.String EXTRA_ASSIST_UID = "android.intent.extra.ASSIST_UID";
+    field public static final java.lang.String EXTRA_AUTO_FILL_ASSIST_STRUCTURE = "android.intent.extra.AUTO_FILL_ASSIST_STRUCTURE";
+    field public static final java.lang.String EXTRA_AUTO_FILL_CALLBACK = "android.intent.extra.AUTO_FILL_CALLBACK";
+    field public static final java.lang.String EXTRA_AUTO_FILL_EXTRAS = "android.intent.extra.AUTO_FILL_EXTRAS";
+    field public static final java.lang.String EXTRA_AUTO_FILL_ITEM_ID = "android.intent.extra.AUTO_FILL_ITEM_ID";
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
     field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -10327,6 +10412,7 @@
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
     field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+    field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
@@ -20443,6 +20529,7 @@
     method public int getContentType();
     method public int getFlags();
     method public int getUsage();
+    method public static int getVolumeControlStream(android.media.AudioAttributes);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
     field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -23586,6 +23673,8 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
+    method public void addQueueItem(android.media.MediaDescription);
+    method public void addQueueItem(android.media.MediaDescription, int);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -23604,6 +23693,8 @@
     method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.media.session.MediaController.Callback);
     method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
+    method public void removeQueueItem(android.media.MediaDescription);
+    method public void removeQueueItemAt(int);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
     method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -23681,11 +23772,14 @@
     method public void setSessionActivity(android.app.PendingIntent);
     method public void setShuffleModeEnabled(boolean);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
     ctor public MediaSession.Callback();
+    method public void onAddQueueItem(android.media.MediaDescription);
+    method public void onAddQueueItem(android.media.MediaDescription, int);
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void onCustomAction(java.lang.String, android.os.Bundle);
     method public void onFastForward();
@@ -23699,6 +23793,8 @@
     method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
     method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
+    method public void onRemoveQueueItem(android.media.MediaDescription);
+    method public void onRemoveQueueItemAt(int);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
@@ -36096,26 +36192,19 @@
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
-    method public void onDatasetAuthenticationRequest(android.os.Bundle, int);
     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 void onFillResponseAuthenticationRequest(android.os.Bundle, int);
     method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, 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 int FLAG_AUTHENTICATION_ERROR = 4; // 0x4
-    field public static final int FLAG_AUTHENTICATION_REQUESTED = 1; // 0x1
-    field public static final int FLAG_AUTHENTICATION_SUCCESS = 2; // 0x2
-    field public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE = 8; // 0x8
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
-  public final class FillCallback {
-    method public void onDatasetAuthentication(android.view.autofill.Dataset, int);
+  public final class FillCallback implements android.os.Parcelable {
+    method public int describeContents();
     method public void onFailure(java.lang.CharSequence);
-    method public void onFillResponseAuthentication(int);
     method public void onSuccess(android.view.autofill.FillResponse);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillCallback> CREATOR;
   }
 
   public final class SaveCallback {
@@ -41952,6 +42041,15 @@
     method public android.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
   }
 
+  public abstract class TransitionListenerAdapter implements android.transition.Transition.TransitionListener {
+    ctor public TransitionListenerAdapter();
+    method public void onTransitionCancel(android.transition.Transition);
+    method public void onTransitionEnd(android.transition.Transition);
+    method public void onTransitionPause(android.transition.Transition);
+    method public void onTransitionResume(android.transition.Transition);
+    method public void onTransitionStart(android.transition.Transition);
+  }
+
   public class TransitionManager {
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
@@ -44268,6 +44366,7 @@
     ctor public View(android.content.Context, android.util.AttributeSet, int);
     ctor public View(android.content.Context, android.util.AttributeSet, int, int);
     method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
+    method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
     method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
@@ -44350,8 +44449,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final <T extends android.view.View> T findViewById(int);
-    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
+    method public final android.view.View findViewById(int);
+    method public final android.view.View findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -44367,7 +44466,8 @@
     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.view.autofill.AutoFillValue getAutoFillValue();
+    method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -44962,6 +45062,7 @@
 
   public static class View.AccessibilityDelegate {
     ctor public View.AccessibilityDelegate();
+    method public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View);
     method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
@@ -46082,6 +46183,7 @@
     method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList();
     method public deprecated int getActions();
+    method public java.util.List<java.lang.String> getAvailableExtraData();
     method public void getBoundsInParent(android.graphics.Rect);
     method public void getBoundsInScreen(android.graphics.Rect);
     method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
@@ -46138,11 +46240,13 @@
     method public boolean performAction(int, android.os.Bundle);
     method public void recycle();
     method public boolean refresh();
+    method public boolean refreshWithExtraData(java.lang.String, android.os.Bundle);
     method public deprecated void removeAction(int);
     method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
     method public boolean removeChild(android.view.View);
     method public boolean removeChild(android.view.View, int);
     method public void setAccessibilityFocused(boolean);
+    method public void setAvailableExtraData(java.util.List<java.lang.String>);
     method public void setBoundsInParent(android.graphics.Rect);
     method public void setBoundsInScreen(android.graphics.Rect);
     method public void setCanOpenPopup(boolean);
@@ -46225,6 +46329,9 @@
     field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
     field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
     field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR;
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
     field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
     field public static final int FOCUS_INPUT = 1; // 0x1
     field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
@@ -46306,6 +46413,7 @@
 
   public abstract class AccessibilityNodeProvider {
     ctor public AccessibilityNodeProvider();
+    method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -46716,11 +46824,11 @@
   }
 
   public final class AutoFillManager {
-    method public void onValueChanged(android.view.View, android.view.autofill.AutoFillValue);
-    method public void updateAutoFillInput(android.view.View, int);
-    method public void updateAutoFillInput(android.view.View, int, android.graphics.Rect, int);
-    field public static final int FLAG_UPDATE_UI_HIDE = 2; // 0x2
-    field public static final int FLAG_UPDATE_UI_SHOW = 1; // 0x1
+    method public void focusChanged(android.view.View, boolean);
+    method public void reset();
+    method public void valueChanged(android.view.View);
+    method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, android.view.autofill.AutoFillValue, boolean);
+    method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
   }
 
   public final class AutoFillType implements android.os.Parcelable {
@@ -46755,10 +46863,9 @@
   }
 
   public static final class Dataset.Builder {
-    ctor public Dataset.Builder(java.lang.CharSequence);
+    ctor public Dataset.Builder(java.lang.String, java.lang.CharSequence);
     method public android.view.autofill.Dataset build();
-    method public android.view.autofill.Dataset.Builder requiresCustomAuthentication(android.os.Bundle, int);
-    method public android.view.autofill.Dataset.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
+    method public android.view.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
     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);
   }
@@ -46770,12 +46877,11 @@
   }
 
   public static final class FillResponse.Builder {
-    ctor public FillResponse.Builder();
+    ctor public FillResponse.Builder(java.lang.String);
     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 requiresCustomAuthentication(android.os.Bundle, int);
-    method public android.view.autofill.FillResponse.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
+    method public android.view.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender);
     method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
   }
 
@@ -46784,13 +46890,6 @@
     method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
   }
 
-  public static abstract class VirtualViewDelegate.Callback {
-    ctor public VirtualViewDelegate.Callback();
-    method public void onAutoFillInputUpdated(int, android.graphics.Rect, int);
-    method public void onNodeRemoved(int...);
-    method public void onValueChanged(int);
-  }
-
 }
 
 package android.view.inputmethod {
@@ -47201,7 +47300,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
@@ -50532,6 +50631,7 @@
     method public void setIs24HourView(java.lang.Boolean);
     method public void setMinute(int);
     method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+    method public boolean validateInput();
   }
 
   public static abstract interface TimePicker.OnTimeChangedListener {
@@ -50930,6 +51030,8 @@
     field public static final int OP_INVOKE_INTERFACE = 114; // 0x72
     field public static final int OP_INVOKE_INTERFACE_JUMBO = 9983; // 0x26ff
     field public static final int OP_INVOKE_INTERFACE_RANGE = 120; // 0x78
+    field public static final int OP_INVOKE_POLYMORPHIC = 250; // 0xfa
+    field public static final int OP_INVOKE_POLYMORPHIC_RANGE = 251; // 0xfb
     field public static final int OP_INVOKE_STATIC = 113; // 0x71
     field public static final int OP_INVOKE_STATIC_JUMBO = 9727; // 0x25ff
     field public static final int OP_INVOKE_STATIC_RANGE = 119; // 0x77
@@ -54224,12 +54326,15 @@
   }
 
   public abstract class MethodHandle {
+    method public java.lang.invoke.MethodHandle asCollector(java.lang.Class<?>, int);
     method public java.lang.invoke.MethodHandle asFixedArity();
+    method public java.lang.invoke.MethodHandle asSpreader(java.lang.Class<?>, int);
     method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
     method public java.lang.invoke.MethodHandle asVarargsCollector(java.lang.Class<?>);
     method public java.lang.invoke.MethodHandle bindTo(java.lang.Object);
     method public final java.lang.Object invoke(java.lang.Object...) throws java.lang.Throwable;
     method public final java.lang.Object invokeExact(java.lang.Object...) throws java.lang.Throwable;
+    method public java.lang.Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable;
     method public java.lang.Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
     method public boolean isVarargsCollector();
     method public java.lang.invoke.MethodType type();
@@ -54263,17 +54368,23 @@
     method public static java.lang.invoke.MethodHandle arrayElementGetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle arrayElementSetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, java.lang.Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle constant(java.lang.Class<?>, java.lang.Object);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle identity(java.lang.Class<?>);
+    method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
     method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandles.Lookup lookup();
     method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
     method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
+    method public static <T extends java.lang.reflect.Member> T reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
     method public static java.lang.invoke.MethodHandle throwException(java.lang.Class<?>, java.lang.Class<? extends java.lang.Throwable>);
   }
 
@@ -54290,6 +54401,7 @@
     method public java.lang.invoke.MethodHandles.Lookup in(java.lang.Class<?>);
     method public java.lang.Class<?> lookupClass();
     method public int lookupModes();
+    method public java.lang.invoke.MethodHandleInfo revealDirect(java.lang.invoke.MethodHandle);
     method public void throwMakeAccessException(java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflect(java.lang.reflect.Method) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflectConstructor(java.lang.reflect.Constructor<?>) throws java.lang.IllegalAccessException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 55b32f6..f77f6bb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -206,6 +206,7 @@
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
     field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
@@ -2807,11 +2808,25 @@
 
 package android.accessibilityservice {
 
+  public final class AccessibilityButtonController {
+    method public boolean isAccessibilityButtonAvailable();
+    method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+    method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback, android.os.Handler);
+    method public void unregisterAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+  }
+
+  public static abstract class AccessibilityButtonController.AccessibilityButtonCallback {
+    ctor public AccessibilityButtonController.AccessibilityButtonCallback();
+    method public void onAvailabilityChanged(android.accessibilityservice.AccessibilityButtonController, boolean);
+    method public void onClicked(android.accessibilityservice.AccessibilityButtonController);
+  }
+
   public abstract class AccessibilityService extends android.app.Service {
     ctor public AccessibilityService();
     method public final void disableSelf();
     method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
     method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2924,6 +2939,7 @@
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+    field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
     field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
     field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
     field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
@@ -5206,15 +5222,20 @@
     ctor public Notification(android.os.Parcel);
     method public android.app.Notification clone();
     method public int describeContents();
+    method public int getBadgeIcon();
     method public java.lang.String getChannel();
     method public java.lang.String getGroup();
     method public android.graphics.drawable.Icon getLargeIcon();
     method public static java.lang.Class<? extends android.app.Notification.Style> getNotificationStyleClass(java.lang.String);
+    method public java.lang.String getShortcutId();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
     method public long getTimeout();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+    field public static final int BADGE_ICON_LARGE = 2; // 0x2
+    field public static final int BADGE_ICON_NONE = 0; // 0x0
+    field public static final int BADGE_ICON_SMALL = 1; // 0x1
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
     field public static final java.lang.String CATEGORY_CALL = "call";
     field public static final java.lang.String CATEGORY_EMAIL = "email";
@@ -5308,7 +5329,7 @@
     field public deprecated int ledARGB;
     field public deprecated int ledOffMS;
     field public deprecated int ledOnMS;
-    field public deprecated int number;
+    field public int number;
     field public deprecated int priority;
     field public android.app.Notification publicVersion;
     field public deprecated android.net.Uri sound;
@@ -5396,6 +5417,7 @@
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
+    method public android.app.Notification.Builder chooseBadgeIcon(int);
     method public android.widget.RemoteViews createBigContentView();
     method public android.widget.RemoteViews createContentView();
     method public android.widget.RemoteViews createHeadsUpContentView();
@@ -5428,13 +5450,14 @@
     method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public deprecated android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
-    method public deprecated android.app.Notification.Builder setNumber(int);
+    method public android.app.Notification.Builder setNumber(int);
     method public android.app.Notification.Builder setOngoing(boolean);
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public deprecated android.app.Notification.Builder setPriority(int);
     method public android.app.Notification.Builder setProgress(int, int, boolean);
     method public android.app.Notification.Builder setPublicVersion(android.app.Notification);
     method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]);
+    method public android.app.Notification.Builder setShortcutId(java.lang.String);
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
@@ -5851,10 +5874,11 @@
   }
 
   public final class RemoteAction implements android.os.Parcelable {
-    ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
+    ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.RemoteAction clone();
     method public int describeContents();
     method public void dump(java.lang.String, java.io.PrintWriter);
+    method public android.app.PendingIntent getActionIntent();
     method public java.lang.CharSequence getContentDescription();
     method public android.graphics.drawable.Icon getIcon();
     method public java.lang.CharSequence getTitle();
@@ -5862,10 +5886,6 @@
     field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
   }
 
-  public static abstract interface RemoteAction.OnActionListener {
-    method public abstract void onAction(android.app.RemoteAction);
-  }
-
   public final class RemoteInput implements android.os.Parcelable {
     method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
     method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
@@ -6204,6 +6224,10 @@
     method public void onDetached();
   }
 
+  public class VrManager {
+    method public void setPersistentVrModeEnabled(boolean);
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6402,6 +6426,7 @@
     method public java.lang.CharSequence getDeviceOwnerOrganizationName();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
+    method public java.lang.String[] getLockTaskPackages(android.content.ComponentName);
     method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
@@ -8329,6 +8354,65 @@
 
 }
 
+package android.companion {
+
+  public final class AssociationRequest<F extends android.companion.DeviceFilter> 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.companion.AssociationRequest> CREATOR;
+  }
+
+  public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
+    method public android.companion.AssociationRequest<F> build();
+    method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
+    method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
+    method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
+    method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+  }
+
+  public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.companion.BluetoothDeviceFilter> CREATOR;
+  }
+
+  public static final class BluetoothDeviceFilter.Builder {
+    ctor public BluetoothDeviceFilter.Builder();
+    method public android.companion.BluetoothDeviceFilter.Builder addServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+    method public android.companion.BluetoothDeviceFilter build();
+    method public android.companion.BluetoothDeviceFilter.Builder setAddress(java.lang.String);
+    method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+  }
+
+  public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+  }
+
+  public static final class BluetoothLEDeviceFilter.Builder {
+    ctor public BluetoothLEDeviceFilter.Builder();
+    method public android.companion.BluetoothLEDeviceFilter build();
+    method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+    method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+  }
+
+  public final class CompanionDeviceManager {
+    method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+    field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+  }
+
+  public static abstract class CompanionDeviceManager.Callback {
+    ctor public CompanionDeviceManager.Callback();
+    method public abstract void onDeviceFound(android.content.IntentSender);
+    method public abstract void onFailure(java.lang.CharSequence);
+  }
+
+  public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
+  }
+
+}
+
 package android.content {
 
   public abstract class AbstractThreadedSyncAdapter {
@@ -8948,6 +9032,7 @@
     field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
     field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub";
@@ -9006,6 +9091,7 @@
     field public static final java.lang.String USB_SERVICE = "usb";
     field public static final java.lang.String USER_SERVICE = "user";
     field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
+    field public static final java.lang.String VR_SERVICE = "vrmanager";
     field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
     field public static final java.lang.String WIFI_AWARE_SERVICE = "wifiaware";
     field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
@@ -9504,6 +9590,10 @@
     field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
     field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
     field public static final java.lang.String EXTRA_ASSIST_UID = "android.intent.extra.ASSIST_UID";
+    field public static final java.lang.String EXTRA_AUTO_FILL_ASSIST_STRUCTURE = "android.intent.extra.AUTO_FILL_ASSIST_STRUCTURE";
+    field public static final java.lang.String EXTRA_AUTO_FILL_CALLBACK = "android.intent.extra.AUTO_FILL_CALLBACK";
+    field public static final java.lang.String EXTRA_AUTO_FILL_EXTRAS = "android.intent.extra.AUTO_FILL_EXTRAS";
+    field public static final java.lang.String EXTRA_AUTO_FILL_ITEM_ID = "android.intent.extra.AUTO_FILL_ITEM_ID";
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
     field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -10815,6 +10905,7 @@
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
     field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+    field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
@@ -21999,6 +22090,7 @@
     method public int getContentType();
     method public int getFlags();
     method public int getUsage();
+    method public static int getVolumeControlStream(android.media.AudioAttributes);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
     field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -25275,6 +25367,8 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
+    method public void addQueueItem(android.media.MediaDescription);
+    method public void addQueueItem(android.media.MediaDescription, int);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -25293,6 +25387,8 @@
     method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.media.session.MediaController.Callback);
     method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
+    method public void removeQueueItem(android.media.MediaDescription);
+    method public void removeQueueItemAt(int);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
     method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -25370,11 +25466,14 @@
     method public void setSessionActivity(android.app.PendingIntent);
     method public void setShuffleModeEnabled(boolean);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
     ctor public MediaSession.Callback();
+    method public void onAddQueueItem(android.media.MediaDescription);
+    method public void onAddQueueItem(android.media.MediaDescription, int);
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void onCustomAction(java.lang.String, android.os.Bundle);
     method public void onFastForward();
@@ -25388,6 +25487,8 @@
     method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
     method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
+    method public void onRemoveQueueItem(android.media.MediaDescription);
+    method public void onRemoveQueueItemAt(int);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
@@ -39128,26 +39229,19 @@
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
-    method public void onDatasetAuthenticationRequest(android.os.Bundle, int);
     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 void onFillResponseAuthenticationRequest(android.os.Bundle, int);
     method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, 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 int FLAG_AUTHENTICATION_ERROR = 4; // 0x4
-    field public static final int FLAG_AUTHENTICATION_REQUESTED = 1; // 0x1
-    field public static final int FLAG_AUTHENTICATION_SUCCESS = 2; // 0x2
-    field public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE = 8; // 0x8
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
-  public final class FillCallback {
-    method public void onDatasetAuthentication(android.view.autofill.Dataset, int);
+  public final class FillCallback implements android.os.Parcelable {
+    method public int describeContents();
     method public void onFailure(java.lang.CharSequence);
-    method public void onFillResponseAuthentication(int);
     method public void onSuccess(android.view.autofill.FillResponse);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillCallback> CREATOR;
   }
 
   public final class SaveCallback {
@@ -45353,6 +45447,15 @@
     method public android.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
   }
 
+  public abstract class TransitionListenerAdapter implements android.transition.Transition.TransitionListener {
+    ctor public TransitionListenerAdapter();
+    method public void onTransitionCancel(android.transition.Transition);
+    method public void onTransitionEnd(android.transition.Transition);
+    method public void onTransitionPause(android.transition.Transition);
+    method public void onTransitionResume(android.transition.Transition);
+    method public void onTransitionStart(android.transition.Transition);
+  }
+
   public class TransitionManager {
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
@@ -47670,6 +47773,7 @@
     ctor public View(android.content.Context, android.util.AttributeSet, int);
     ctor public View(android.content.Context, android.util.AttributeSet, int, int);
     method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
+    method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
     method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
@@ -47752,8 +47856,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final <T extends android.view.View> T findViewById(int);
-    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
+    method public final android.view.View findViewById(int);
+    method public final android.view.View findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -47769,7 +47873,8 @@
     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.view.autofill.AutoFillValue getAutoFillValue();
+    method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -48364,6 +48469,7 @@
 
   public static class View.AccessibilityDelegate {
     ctor public View.AccessibilityDelegate();
+    method public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View);
     method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
@@ -49487,6 +49593,7 @@
     method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList();
     method public deprecated int getActions();
+    method public java.util.List<java.lang.String> getAvailableExtraData();
     method public void getBoundsInParent(android.graphics.Rect);
     method public void getBoundsInScreen(android.graphics.Rect);
     method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
@@ -49543,11 +49650,13 @@
     method public boolean performAction(int, android.os.Bundle);
     method public void recycle();
     method public boolean refresh();
+    method public boolean refreshWithExtraData(java.lang.String, android.os.Bundle);
     method public deprecated void removeAction(int);
     method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
     method public boolean removeChild(android.view.View);
     method public boolean removeChild(android.view.View, int);
     method public void setAccessibilityFocused(boolean);
+    method public void setAvailableExtraData(java.util.List<java.lang.String>);
     method public void setBoundsInParent(android.graphics.Rect);
     method public void setBoundsInScreen(android.graphics.Rect);
     method public void setCanOpenPopup(boolean);
@@ -49630,6 +49739,9 @@
     field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
     field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
     field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR;
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
     field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
     field public static final int FOCUS_INPUT = 1; // 0x1
     field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
@@ -49711,6 +49823,7 @@
 
   public abstract class AccessibilityNodeProvider {
     ctor public AccessibilityNodeProvider();
+    method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -50121,11 +50234,11 @@
   }
 
   public final class AutoFillManager {
-    method public void onValueChanged(android.view.View, android.view.autofill.AutoFillValue);
-    method public void updateAutoFillInput(android.view.View, int);
-    method public void updateAutoFillInput(android.view.View, int, android.graphics.Rect, int);
-    field public static final int FLAG_UPDATE_UI_HIDE = 2; // 0x2
-    field public static final int FLAG_UPDATE_UI_SHOW = 1; // 0x1
+    method public void focusChanged(android.view.View, boolean);
+    method public void reset();
+    method public void valueChanged(android.view.View);
+    method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, android.view.autofill.AutoFillValue, boolean);
+    method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
   }
 
   public final class AutoFillType implements android.os.Parcelable {
@@ -50160,10 +50273,9 @@
   }
 
   public static final class Dataset.Builder {
-    ctor public Dataset.Builder(java.lang.CharSequence);
+    ctor public Dataset.Builder(java.lang.String, java.lang.CharSequence);
     method public android.view.autofill.Dataset build();
-    method public android.view.autofill.Dataset.Builder requiresCustomAuthentication(android.os.Bundle, int);
-    method public android.view.autofill.Dataset.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
+    method public android.view.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
     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);
   }
@@ -50175,12 +50287,11 @@
   }
 
   public static final class FillResponse.Builder {
-    ctor public FillResponse.Builder();
+    ctor public FillResponse.Builder(java.lang.String);
     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 requiresCustomAuthentication(android.os.Bundle, int);
-    method public android.view.autofill.FillResponse.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
+    method public android.view.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender);
     method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
   }
 
@@ -50189,13 +50300,6 @@
     method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
   }
 
-  public static abstract class VirtualViewDelegate.Callback {
-    ctor public VirtualViewDelegate.Callback();
-    method public void onAutoFillInputUpdated(int, android.graphics.Rect, int);
-    method public void onNodeRemoved(int...);
-    method public void onValueChanged(int);
-  }
-
 }
 
 package android.view.inputmethod {
@@ -50606,7 +50710,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
@@ -54298,6 +54402,7 @@
     method public void setIs24HourView(java.lang.Boolean);
     method public void setMinute(int);
     method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+    method public boolean validateInput();
   }
 
   public static abstract interface TimePicker.OnTimeChangedListener {
@@ -54696,6 +54801,8 @@
     field public static final int OP_INVOKE_INTERFACE = 114; // 0x72
     field public static final int OP_INVOKE_INTERFACE_JUMBO = 9983; // 0x26ff
     field public static final int OP_INVOKE_INTERFACE_RANGE = 120; // 0x78
+    field public static final int OP_INVOKE_POLYMORPHIC = 250; // 0xfa
+    field public static final int OP_INVOKE_POLYMORPHIC_RANGE = 251; // 0xfb
     field public static final int OP_INVOKE_STATIC = 113; // 0x71
     field public static final int OP_INVOKE_STATIC_JUMBO = 9727; // 0x25ff
     field public static final int OP_INVOKE_STATIC_RANGE = 119; // 0x77
@@ -57990,12 +58097,15 @@
   }
 
   public abstract class MethodHandle {
+    method public java.lang.invoke.MethodHandle asCollector(java.lang.Class<?>, int);
     method public java.lang.invoke.MethodHandle asFixedArity();
+    method public java.lang.invoke.MethodHandle asSpreader(java.lang.Class<?>, int);
     method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
     method public java.lang.invoke.MethodHandle asVarargsCollector(java.lang.Class<?>);
     method public java.lang.invoke.MethodHandle bindTo(java.lang.Object);
     method public final java.lang.Object invoke(java.lang.Object...) throws java.lang.Throwable;
     method public final java.lang.Object invokeExact(java.lang.Object...) throws java.lang.Throwable;
+    method public java.lang.Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable;
     method public java.lang.Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
     method public boolean isVarargsCollector();
     method public java.lang.invoke.MethodType type();
@@ -58029,17 +58139,23 @@
     method public static java.lang.invoke.MethodHandle arrayElementGetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle arrayElementSetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, java.lang.Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle constant(java.lang.Class<?>, java.lang.Object);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle identity(java.lang.Class<?>);
+    method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
     method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandles.Lookup lookup();
     method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
     method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
+    method public static <T extends java.lang.reflect.Member> T reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
     method public static java.lang.invoke.MethodHandle throwException(java.lang.Class<?>, java.lang.Class<? extends java.lang.Throwable>);
   }
 
@@ -58056,6 +58172,7 @@
     method public java.lang.invoke.MethodHandles.Lookup in(java.lang.Class<?>);
     method public java.lang.Class<?> lookupClass();
     method public int lookupModes();
+    method public java.lang.invoke.MethodHandleInfo revealDirect(java.lang.invoke.MethodHandle);
     method public void throwMakeAccessException(java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflect(java.lang.reflect.Method) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflectConstructor(java.lang.reflect.Constructor<?>) throws java.lang.IllegalAccessException;
diff --git a/api/test-current.txt b/api/test-current.txt
index bc7a001..37da0d3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -118,6 +118,7 @@
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
+    field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -2688,11 +2689,25 @@
 
 package android.accessibilityservice {
 
+  public final class AccessibilityButtonController {
+    method public boolean isAccessibilityButtonAvailable();
+    method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+    method public void registerAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback, android.os.Handler);
+    method public void unregisterAccessibilityButtonCallback(android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback);
+  }
+
+  public static abstract class AccessibilityButtonController.AccessibilityButtonCallback {
+    ctor public AccessibilityButtonController.AccessibilityButtonCallback();
+    method public void onAvailabilityChanged(android.accessibilityservice.AccessibilityButtonController, boolean);
+    method public void onClicked(android.accessibilityservice.AccessibilityButtonController);
+  }
+
   public abstract class AccessibilityService extends android.app.Service {
     ctor public AccessibilityService();
     method public final void disableSelf();
     method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
+    method public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
     method public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
     method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2805,6 +2820,7 @@
     field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
     field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
+    field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
     field public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 8; // 0x8
     field public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 32; // 0x20
     field public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 4; // 0x4
@@ -5056,14 +5072,19 @@
     ctor public Notification(android.os.Parcel);
     method public android.app.Notification clone();
     method public int describeContents();
+    method public int getBadgeIcon();
     method public java.lang.String getChannel();
     method public java.lang.String getGroup();
     method public android.graphics.drawable.Icon getLargeIcon();
+    method public java.lang.String getShortcutId();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
     method public long getTimeout();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
+    field public static final int BADGE_ICON_LARGE = 2; // 0x2
+    field public static final int BADGE_ICON_NONE = 0; // 0x0
+    field public static final int BADGE_ICON_SMALL = 1; // 0x1
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
     field public static final java.lang.String CATEGORY_CALL = "call";
     field public static final java.lang.String CATEGORY_EMAIL = "email";
@@ -5155,7 +5176,7 @@
     field public deprecated int ledARGB;
     field public deprecated int ledOffMS;
     field public deprecated int ledOnMS;
-    field public deprecated int number;
+    field public int number;
     field public deprecated int priority;
     field public android.app.Notification publicVersion;
     field public deprecated android.net.Uri sound;
@@ -5243,6 +5264,7 @@
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
+    method public android.app.Notification.Builder chooseBadgeIcon(int);
     method public android.widget.RemoteViews createBigContentView();
     method public android.widget.RemoteViews createContentView();
     method public android.widget.RemoteViews createHeadsUpContentView();
@@ -5275,13 +5297,14 @@
     method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public deprecated android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
-    method public deprecated android.app.Notification.Builder setNumber(int);
+    method public android.app.Notification.Builder setNumber(int);
     method public android.app.Notification.Builder setOngoing(boolean);
     method public android.app.Notification.Builder setOnlyAlertOnce(boolean);
     method public deprecated android.app.Notification.Builder setPriority(int);
     method public android.app.Notification.Builder setProgress(int, int, boolean);
     method public android.app.Notification.Builder setPublicVersion(android.app.Notification);
     method public android.app.Notification.Builder setRemoteInputHistory(java.lang.CharSequence[]);
+    method public android.app.Notification.Builder setShortcutId(java.lang.String);
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
@@ -5666,10 +5689,11 @@
   }
 
   public final class RemoteAction implements android.os.Parcelable {
-    ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
+    ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.RemoteAction clone();
     method public int describeContents();
     method public void dump(java.lang.String, java.io.PrintWriter);
+    method public android.app.PendingIntent getActionIntent();
     method public java.lang.CharSequence getContentDescription();
     method public android.graphics.drawable.Icon getIcon();
     method public java.lang.CharSequence getTitle();
@@ -5677,10 +5701,6 @@
     field public static final android.os.Parcelable.Creator<android.app.RemoteAction> CREATOR;
   }
 
-  public static abstract interface RemoteAction.OnActionListener {
-    method public abstract void onAction(android.app.RemoteAction);
-  }
-
   public final class RemoteInput implements android.os.Parcelable {
     method public static void addDataResultToIntent(android.app.RemoteInput, android.content.Intent, java.util.Map<java.lang.String, android.net.Uri>);
     method public static void addResultsToIntent(android.app.RemoteInput[], android.content.Intent, android.os.Bundle);
@@ -6216,6 +6236,7 @@
     method public long getLastBugReportRequestTime();
     method public long getLastNetworkLogRetrievalTime();
     method public long getLastSecurityLogRetrievalTime();
+    method public java.lang.String[] getLockTaskPackages(android.content.ComponentName);
     method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
@@ -7966,6 +7987,65 @@
 
 }
 
+package android.companion {
+
+  public final class AssociationRequest<F extends android.companion.DeviceFilter> 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.companion.AssociationRequest> CREATOR;
+  }
+
+  public static final class AssociationRequest.Builder<F extends android.companion.DeviceFilter> {
+    method public android.companion.AssociationRequest<F> build();
+    method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothDeviceFilter> createForBluetoothDevice();
+    method public static android.companion.AssociationRequest.Builder<android.companion.BluetoothLEDeviceFilter> createForBluetoothLEDevice();
+    method public android.companion.AssociationRequest.Builder<F> setDeviceFilter(F);
+    method public android.companion.AssociationRequest.Builder<F> setSingleDevice(boolean);
+  }
+
+  public final class BluetoothDeviceFilter implements android.companion.DeviceFilter {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.companion.BluetoothDeviceFilter> CREATOR;
+  }
+
+  public static final class BluetoothDeviceFilter.Builder {
+    ctor public BluetoothDeviceFilter.Builder();
+    method public android.companion.BluetoothDeviceFilter.Builder addServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+    method public android.companion.BluetoothDeviceFilter build();
+    method public android.companion.BluetoothDeviceFilter.Builder setAddress(java.lang.String);
+    method public android.companion.BluetoothDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+  }
+
+  public final class BluetoothLEDeviceFilter implements android.companion.DeviceFilter {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.companion.BluetoothLEDeviceFilter> CREATOR;
+  }
+
+  public static final class BluetoothLEDeviceFilter.Builder {
+    ctor public BluetoothLEDeviceFilter.Builder();
+    method public android.companion.BluetoothLEDeviceFilter build();
+    method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern);
+    method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter);
+  }
+
+  public final class CompanionDeviceManager {
+    method public void associate(android.companion.AssociationRequest<?>, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
+    field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+  }
+
+  public static abstract class CompanionDeviceManager.Callback {
+    ctor public CompanionDeviceManager.Callback();
+    method public abstract void onDeviceFound(android.content.IntentSender);
+    method public abstract void onFailure(java.lang.CharSequence);
+  }
+
+  public abstract interface DeviceFilter<D extends android.os.Parcelable> implements android.os.Parcelable {
+  }
+
+}
+
 package android.content {
 
   public abstract class AbstractThreadedSyncAdapter {
@@ -8580,6 +8660,7 @@
     field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
     field public static final java.lang.String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
+    field public static final java.lang.String COMPANION_DEVICE_SERVICE = "companion_device";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -9118,6 +9199,10 @@
     field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
     field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
     field public static final java.lang.String EXTRA_ASSIST_UID = "android.intent.extra.ASSIST_UID";
+    field public static final java.lang.String EXTRA_AUTO_FILL_ASSIST_STRUCTURE = "android.intent.extra.AUTO_FILL_ASSIST_STRUCTURE";
+    field public static final java.lang.String EXTRA_AUTO_FILL_CALLBACK = "android.intent.extra.AUTO_FILL_CALLBACK";
+    field public static final java.lang.String EXTRA_AUTO_FILL_EXTRAS = "android.intent.extra.AUTO_FILL_EXTRAS";
+    field public static final java.lang.String EXTRA_AUTO_FILL_ITEM_ID = "android.intent.extra.AUTO_FILL_ITEM_ID";
     field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
     field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
     field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -10359,6 +10444,7 @@
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
     field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
+    field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_VERSION = "android.hardware.vulkan.version";
     field public static final java.lang.String FEATURE_WATCH = "android.hardware.type.watch";
@@ -20535,6 +20621,7 @@
     method public int getContentType();
     method public int getFlags();
     method public int getUsage();
+    method public static int getVolumeControlStream(android.media.AudioAttributes);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
     field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
@@ -23678,6 +23765,8 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
+    method public void addQueueItem(android.media.MediaDescription);
+    method public void addQueueItem(android.media.MediaDescription, int);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -23696,6 +23785,8 @@
     method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.media.session.MediaController.Callback);
     method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
+    method public void removeQueueItem(android.media.MediaDescription);
+    method public void removeQueueItemAt(int);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
     method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -23773,11 +23864,14 @@
     method public void setSessionActivity(android.app.PendingIntent);
     method public void setShuffleModeEnabled(boolean);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
     ctor public MediaSession.Callback();
+    method public void onAddQueueItem(android.media.MediaDescription);
+    method public void onAddQueueItem(android.media.MediaDescription, int);
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void onCustomAction(java.lang.String, android.os.Bundle);
     method public void onFastForward();
@@ -23791,6 +23885,8 @@
     method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
     method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
+    method public void onRemoveQueueItem(android.media.MediaDescription);
+    method public void onRemoveQueueItemAt(int);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
@@ -36231,26 +36327,19 @@
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
-    method public void onDatasetAuthenticationRequest(android.os.Bundle, int);
     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 void onFillResponseAuthenticationRequest(android.os.Bundle, int);
     method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, 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 int FLAG_AUTHENTICATION_ERROR = 4; // 0x4
-    field public static final int FLAG_AUTHENTICATION_REQUESTED = 1; // 0x1
-    field public static final int FLAG_AUTHENTICATION_SUCCESS = 2; // 0x2
-    field public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE = 8; // 0x8
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
-  public final class FillCallback {
-    method public void onDatasetAuthentication(android.view.autofill.Dataset, int);
+  public final class FillCallback implements android.os.Parcelable {
+    method public int describeContents();
     method public void onFailure(java.lang.CharSequence);
-    method public void onFillResponseAuthentication(int);
     method public void onSuccess(android.view.autofill.FillResponse);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillCallback> CREATOR;
   }
 
   public final class SaveCallback {
@@ -42091,6 +42180,15 @@
     method public android.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
   }
 
+  public abstract class TransitionListenerAdapter implements android.transition.Transition.TransitionListener {
+    ctor public TransitionListenerAdapter();
+    method public void onTransitionCancel(android.transition.Transition);
+    method public void onTransitionEnd(android.transition.Transition);
+    method public void onTransitionPause(android.transition.Transition);
+    method public void onTransitionResume(android.transition.Transition);
+    method public void onTransitionStart(android.transition.Transition);
+  }
+
   public class TransitionManager {
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
@@ -44574,6 +44672,7 @@
     ctor public View(android.content.Context, android.util.AttributeSet, int);
     ctor public View(android.content.Context, android.util.AttributeSet, int, int);
     method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
+    method public void addExtraDataToAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
     method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
@@ -44656,8 +44755,8 @@
     method public void drawableHotspotChanged(float, float);
     method protected void drawableStateChanged();
     method public android.view.View findFocus();
-    method public final <T extends android.view.View> T findViewById(int);
-    method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
+    method public final android.view.View findViewById(int);
+    method public final android.view.View findViewWithTag(java.lang.Object);
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
@@ -44673,7 +44772,8 @@
     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.view.autofill.AutoFillValue getAutoFillValue();
+    method public android.view.autofill.VirtualViewDelegate getAutoFillVirtualViewDelegate();
     method public android.graphics.drawable.Drawable getBackground();
     method public android.content.res.ColorStateList getBackgroundTintList();
     method public android.graphics.PorterDuff.Mode getBackgroundTintMode();
@@ -45269,6 +45369,7 @@
 
   public static class View.AccessibilityDelegate {
     ctor public View.AccessibilityDelegate();
+    method public void addExtraDataToAccessibilityNodeInfo(android.view.View, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
     method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(android.view.View);
     method public void onInitializeAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
@@ -46393,6 +46494,7 @@
     method public android.view.accessibility.AccessibilityNodeInfo focusSearch(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> getActionList();
     method public deprecated int getActions();
+    method public java.util.List<java.lang.String> getAvailableExtraData();
     method public void getBoundsInParent(android.graphics.Rect);
     method public void getBoundsInScreen(android.graphics.Rect);
     method public android.view.accessibility.AccessibilityNodeInfo getChild(int);
@@ -46449,11 +46551,13 @@
     method public boolean performAction(int, android.os.Bundle);
     method public void recycle();
     method public boolean refresh();
+    method public boolean refreshWithExtraData(java.lang.String, android.os.Bundle);
     method public deprecated void removeAction(int);
     method public boolean removeAction(android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction);
     method public boolean removeChild(android.view.View);
     method public boolean removeChild(android.view.View, int);
     method public void setAccessibilityFocused(boolean);
+    method public void setAvailableExtraData(java.util.List<java.lang.String>);
     method public void setBoundsInParent(android.graphics.Rect);
     method public void setBoundsInScreen(android.graphics.Rect);
     method public void setCanOpenPopup(boolean);
@@ -46537,6 +46641,9 @@
     field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
     field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
     field public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR;
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+    field public static final java.lang.String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
     field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
     field public static final int FOCUS_INPUT = 1; // 0x1
     field public static final int MOVEMENT_GRANULARITY_CHARACTER = 1; // 0x1
@@ -46618,6 +46725,7 @@
 
   public abstract class AccessibilityNodeProvider {
     ctor public AccessibilityNodeProvider();
+    method public void addExtraDataToAccessibilityNodeInfo(int, android.view.accessibility.AccessibilityNodeInfo, java.lang.String, android.os.Bundle);
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -47029,11 +47137,11 @@
   }
 
   public final class AutoFillManager {
-    method public void onValueChanged(android.view.View, android.view.autofill.AutoFillValue);
-    method public void updateAutoFillInput(android.view.View, int);
-    method public void updateAutoFillInput(android.view.View, int, android.graphics.Rect, int);
-    field public static final int FLAG_UPDATE_UI_HIDE = 2; // 0x2
-    field public static final int FLAG_UPDATE_UI_SHOW = 1; // 0x1
+    method public void focusChanged(android.view.View, boolean);
+    method public void reset();
+    method public void valueChanged(android.view.View);
+    method public void virtualFocusChanged(android.view.View, int, android.graphics.Rect, android.view.autofill.AutoFillValue, boolean);
+    method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue);
   }
 
   public final class AutoFillType implements android.os.Parcelable {
@@ -47068,10 +47176,9 @@
   }
 
   public static final class Dataset.Builder {
-    ctor public Dataset.Builder(java.lang.CharSequence);
+    ctor public Dataset.Builder(java.lang.String, java.lang.CharSequence);
     method public android.view.autofill.Dataset build();
-    method public android.view.autofill.Dataset.Builder requiresCustomAuthentication(android.os.Bundle, int);
-    method public android.view.autofill.Dataset.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
+    method public android.view.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
     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);
   }
@@ -47083,12 +47190,11 @@
   }
 
   public static final class FillResponse.Builder {
-    ctor public FillResponse.Builder();
+    ctor public FillResponse.Builder(java.lang.String);
     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 requiresCustomAuthentication(android.os.Bundle, int);
-    method public android.view.autofill.FillResponse.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
+    method public android.view.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender);
     method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
   }
 
@@ -47097,13 +47203,6 @@
     method public abstract void autoFill(int, android.view.autofill.AutoFillValue);
   }
 
-  public static abstract class VirtualViewDelegate.Callback {
-    ctor public VirtualViewDelegate.Callback();
-    method public void onAutoFillInputUpdated(int, android.graphics.Rect, int);
-    method public void onNodeRemoved(int...);
-    method public void onValueChanged(int);
-  }
-
 }
 
 package android.view.inputmethod {
@@ -47514,7 +47613,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
@@ -50857,6 +50956,7 @@
     method public void setIs24HourView(java.lang.Boolean);
     method public void setMinute(int);
     method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener);
+    method public boolean validateInput();
     field public static final int MODE_CLOCK = 2; // 0x2
     field public static final int MODE_SPINNER = 1; // 0x1
   }
@@ -51258,6 +51358,8 @@
     field public static final int OP_INVOKE_INTERFACE = 114; // 0x72
     field public static final int OP_INVOKE_INTERFACE_JUMBO = 9983; // 0x26ff
     field public static final int OP_INVOKE_INTERFACE_RANGE = 120; // 0x78
+    field public static final int OP_INVOKE_POLYMORPHIC = 250; // 0xfa
+    field public static final int OP_INVOKE_POLYMORPHIC_RANGE = 251; // 0xfb
     field public static final int OP_INVOKE_STATIC = 113; // 0x71
     field public static final int OP_INVOKE_STATIC_JUMBO = 9727; // 0x25ff
     field public static final int OP_INVOKE_STATIC_RANGE = 119; // 0x77
@@ -54552,12 +54654,15 @@
   }
 
   public abstract class MethodHandle {
+    method public java.lang.invoke.MethodHandle asCollector(java.lang.Class<?>, int);
     method public java.lang.invoke.MethodHandle asFixedArity();
+    method public java.lang.invoke.MethodHandle asSpreader(java.lang.Class<?>, int);
     method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
     method public java.lang.invoke.MethodHandle asVarargsCollector(java.lang.Class<?>);
     method public java.lang.invoke.MethodHandle bindTo(java.lang.Object);
     method public final java.lang.Object invoke(java.lang.Object...) throws java.lang.Throwable;
     method public final java.lang.Object invokeExact(java.lang.Object...) throws java.lang.Throwable;
+    method public java.lang.Object invokeWithArguments(java.lang.Object...) throws java.lang.Throwable;
     method public java.lang.Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
     method public boolean isVarargsCollector();
     method public java.lang.invoke.MethodType type();
@@ -54591,17 +54696,23 @@
     method public static java.lang.invoke.MethodHandle arrayElementGetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle arrayElementSetter(java.lang.Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, java.lang.Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle constant(java.lang.Class<?>, java.lang.Object);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle identity(java.lang.Class<?>);
+    method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
     method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandles.Lookup lookup();
     method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
     method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
+    method public static <T extends java.lang.reflect.Member> T reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
     method public static java.lang.invoke.MethodHandle throwException(java.lang.Class<?>, java.lang.Class<? extends java.lang.Throwable>);
   }
 
@@ -54618,6 +54729,7 @@
     method public java.lang.invoke.MethodHandles.Lookup in(java.lang.Class<?>);
     method public java.lang.Class<?> lookupClass();
     method public int lookupModes();
+    method public java.lang.invoke.MethodHandleInfo revealDirect(java.lang.invoke.MethodHandle);
     method public void throwMakeAccessException(java.lang.String, java.lang.Object) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflect(java.lang.reflect.Method) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflectConstructor(java.lang.reflect.Constructor<?>) throws java.lang.IllegalAccessException;
diff --git a/core/java/android/accessibilityservice/AccessibilityButtonController.java b/core/java/android/accessibilityservice/AccessibilityButtonController.java
new file mode 100644
index 0000000..c3a5dab
--- /dev/null
+++ b/core/java/android/accessibilityservice/AccessibilityButtonController.java
@@ -0,0 +1,223 @@
+/*
+ * 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.accessibilityservice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+/**
+ * Controller for the accessibility button within the system's navigation area
+ * <p>
+ * This class may be used to query the accessibility button's state and register
+ * callbacks for interactions with and state changes to the accessibility button when
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This class and
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} should not be used as
+ * the sole means for offering functionality to users via an {@link AccessibilityService}.
+ * Some device implementations may choose not to provide a software-rendered system
+ * navigation area, making this affordance permanently unavailable.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> On device implementations where the accessibility button is
+ * supported, it may not be available at all times, such as when a foreground application uses
+ * {@link android.view.View#SYSTEM_UI_FLAG_HIDE_NAVIGATION}. A user may also choose to assign
+ * this button to another accessibility service or feature. In each of these cases, a
+ * registered {@link AccessibilityButtonCallback}'s
+ * {@link AccessibilityButtonCallback#onAvailabilityChanged(AccessibilityButtonController, boolean)}
+ * method will be invoked to provide notifications of changes in the accessibility button's
+ * availability to the registering service.
+ * </p>
+ */
+public final class AccessibilityButtonController {
+    private static final String LOG_TAG = "A11yButtonController";
+
+    private final IAccessibilityServiceConnection mServiceConnection;
+    private final Object mLock;
+    private ArrayMap<AccessibilityButtonCallback, Handler> mCallbacks;
+
+    AccessibilityButtonController(@NonNull IAccessibilityServiceConnection serviceConnection) {
+        mServiceConnection = serviceConnection;
+        mLock = new Object();
+    }
+
+    /**
+     * Retrieves whether the accessibility button in the system's navigation area is
+     * available to the calling service.
+     * <p>
+     * <strong>Note:</strong> If the service is not yet connected (e.g.
+     * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
+     * service has been disconnected, this method will have no effect and return {@code false}.
+     * </p>
+     *
+     * @return {@code true} if the accessibility button in the system's navigation area is
+     * available to the calling service, {@code false} otherwise
+     */
+    public boolean isAccessibilityButtonAvailable() {
+        try {
+            return mServiceConnection.isAccessibilityButtonAvailable();
+        } catch (RemoteException re) {
+            Slog.w(LOG_TAG, "Failed to get accessibility button availability.", re);
+            re.rethrowFromSystemServer();
+            return false;
+        }
+    }
+
+    /**
+     * Registers the provided {@link AccessibilityButtonCallback} for interaction and state
+     * changes callbacks related to the accessibility button.
+     *
+     * @param callback the callback to add, must be non-null
+     */
+    public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback) {
+        registerAccessibilityButtonCallback(callback, null);
+    }
+
+    /**
+     * Registers the provided {@link AccessibilityButtonCallback} for interaction and state
+     * change callbacks related to the accessibility button. The callback will occur on the
+     * specified {@link Handler}'s thread, or on the services's main thread if the handler is
+     * {@code null}.
+     *
+     * @param callback the callback to add, must be non-null
+     * @param handler the handler on which to callback should execute, or {@code null} to
+     *                execute on the service's main thread
+     */
+    public void registerAccessibilityButtonCallback(@NonNull AccessibilityButtonCallback callback,
+            @Nullable Handler handler) {
+        synchronized (mLock) {
+            if (mCallbacks == null) {
+                mCallbacks = new ArrayMap<>();
+            }
+
+            mCallbacks.put(callback, handler);
+        }
+    }
+
+    /**
+     * Unregisters the provided {@link AccessibilityButtonCallback} for interaction and state
+     * change callbacks related to the accessibility button.
+     *
+     * @param callback the callback to remove, must be non-null
+     */
+    public void unregisterAccessibilityButtonCallback(
+            @NonNull AccessibilityButtonCallback callback) {
+        synchronized (mLock) {
+            if (mCallbacks == null) {
+                return;
+            }
+
+            final int keyIndex = mCallbacks.indexOfKey(callback);
+            final boolean hasKey = keyIndex >= 0;
+            if (hasKey) {
+                mCallbacks.removeAt(keyIndex);
+            }
+        }
+    }
+
+    /**
+     * Dispatches the accessibility button click to any registered callbacks. This should
+     * be called on the service's main thread.
+     */
+    void dispatchAccessibilityButtonClicked() {
+        final ArrayMap<AccessibilityButtonCallback, Handler> entries;
+        synchronized (mLock) {
+            if (mCallbacks == null || mCallbacks.isEmpty()) {
+                Slog.w(LOG_TAG, "Received accessibility button click with no callbacks!");
+                return;
+            }
+
+            // Callbacks may remove themselves. Perform a shallow copy to avoid concurrent
+            // modification.
+            entries = new ArrayMap<>(mCallbacks);
+        }
+
+        for (int i = 0, count = entries.size(); i < count; i++) {
+            final AccessibilityButtonCallback callback = entries.keyAt(i);
+            final Handler handler = entries.valueAt(i);
+            if (handler != null) {
+                handler.post(() -> callback.onClicked(this));
+            } else {
+                // We're already on the main thread, just run the callback.
+                callback.onClicked(this);
+            }
+        }
+    }
+
+    /**
+     * Dispatches the accessibility button availability changes to any registered callbacks.
+     * This should be called on the service's main thread.
+     */
+    void dispatchAccessibilityButtonAvailabilityChanged(boolean available) {
+        final ArrayMap<AccessibilityButtonCallback, Handler> entries;
+        synchronized (mLock) {
+            if (mCallbacks == null || mCallbacks.isEmpty()) {
+                Slog.w(LOG_TAG,
+                        "Received accessibility button availability change with no callbacks!");
+                return;
+            }
+
+            // Callbacks may remove themselves. Perform a shallow copy to avoid concurrent
+            // modification.
+            entries = new ArrayMap<>(mCallbacks);
+        }
+
+        for (int i = 0, count = entries.size(); i < count; i++) {
+            final AccessibilityButtonCallback callback = entries.keyAt(i);
+            final Handler handler = entries.valueAt(i);
+            if (handler != null) {
+                handler.post(() -> callback.onAvailabilityChanged(this, available));
+            } else {
+                // We're already on the main thread, just run the callback.
+                callback.onAvailabilityChanged(this, available);
+            }
+        }
+    }
+
+    /**
+     * Callback for interaction with and changes to state of the accessibility button
+     * within the system's navigation area.
+     */
+    public static abstract class AccessibilityButtonCallback {
+
+        /**
+         * Called when the accessibility button in the system's navigation area is clicked.
+         *
+         * @param controller the controller used to register for this callback
+         */
+        public void onClicked(AccessibilityButtonController controller) {}
+
+        /**
+         * Called when the availability of the accessibility button in the system's
+         * navigation area has changed. The accessibility button may become unavailable
+         * because the device shopped showing the button, the button was assigned to another
+         * service, or for other reasons.
+         *
+         * @param controller the controller used to register for this callback
+         * @param available {@code true} if the accessibility button is available to this
+         *                  service, {@code false} otherwise
+         */
+        public void onAvailabilityChanged(AccessibilityButtonController controller,
+                boolean available) {
+        }
+    }
+}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index a036b6a..9e486d5 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -378,6 +378,8 @@
         void onPerformGestureResult(int sequence, boolean completedSuccessfully);
         void onFingerprintCapturingGesturesChanged(boolean active);
         void onFingerprintGesture(int gesture);
+        void onAccessibilityButtonClicked();
+        void onAccessibilityButtonAvailabilityChanged(boolean available);
     }
 
     /**
@@ -400,6 +402,7 @@
 
     private MagnificationController mMagnificationController;
     private SoftKeyboardController mSoftKeyboardController;
+    private AccessibilityButtonController mAccessibilityButtonController;
 
     private int mGestureStatusCallbackSequence;
 
@@ -431,6 +434,9 @@
         if (mMagnificationController != null) {
             mMagnificationController.onServiceConnected();
         }
+        if (mSoftKeyboardController != null) {
+            mSoftKeyboardController.onServiceConnected();
+        }
 
         // The client gets to handle service connection last, after we've set
         // up any state upon which their code may rely.
@@ -809,12 +815,10 @@
         }
 
         /**
-         * Removes all instances of the specified change listener from the list
-         * of magnification change listeners.
+         * Removes the specified change listener from the list of magnification change listeners.
          *
          * @param listener the listener to remove, must be non-null
-         * @return {@code true} if at least one instance of the listener was
-         *         removed
+         * @return {@code true} if the listener was removed, {@code false} otherwise
          */
         public boolean removeListener(@NonNull OnMagnificationChangedListener listener) {
             if (mListeners == null) {
@@ -1203,11 +1207,11 @@
         }
 
         /**
-         * Removes all instances of the specified change listener from the list of magnification
-         * change listeners.
+         * Removes the specified change listener from the list of keyboard show mode change
+         * listeners.
          *
          * @param listener the listener to remove, must be non-null
-         * @return {@code true} if at least one instance of the listener was removed
+         * @return {@code true} if the listener was removed, {@code false} otherwise
          */
         public boolean removeOnShowModeChangedListener(@NonNull OnShowModeChangedListener listener) {
             if (mListeners == null) {
@@ -1252,7 +1256,7 @@
             final ArrayMap<OnShowModeChangedListener, Handler> entries;
             synchronized (mLock) {
                 if (mListeners == null || mListeners.isEmpty()) {
-                    Slog.d(LOG_TAG, "Received soft keyboard show mode changed callback"
+                    Slog.w(LOG_TAG, "Received soft keyboard show mode changed callback"
                             + " with no listeners registered!");
                     setSoftKeyboardCallbackEnabled(false);
                     return;
@@ -1308,9 +1312,9 @@
          * The lastto this method will be honored, regardless of any previous calls (including those
          * made by other AccessibilityServices).
          * <p>
-         * <strong>Note:</strong> If the service is not yet conected (e.g.
+         * <strong>Note:</strong> If the service is not yet connected (e.g.
          * {@link AccessibilityService#onServiceConnected()} has not yet been called) or the
-         * service has been disconnected, this method will hav no effect and return {@code false}.
+         * service has been disconnected, this method will have no effect and return {@code false}.
          *
          * @param showMode the new show mode for the soft keyboard
          * @return {@code true} on success
@@ -1349,6 +1353,39 @@
     }
 
     /**
+     * Returns the controller for the accessibility button within the system's navigation area.
+     * This instance may be used to query the accessibility button's state and register listeners
+     * for interactions with and state changes for the accessibility button when
+     * {@link AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} is set.
+     * <p>
+     * <strong>Note:</strong> Not all devices are capable of displaying the accessibility button
+     * within a navigation area, and as such, use of this class should be considered only as an
+     * optional feature or shortcut on supported device implementations.
+     * </p>
+     *
+     * @return the accessibility button controller for this {@link AccessibilityService}
+     */
+    @NonNull
+    public final AccessibilityButtonController getAccessibilityButtonController() {
+        synchronized (mLock) {
+            if (mAccessibilityButtonController == null) {
+                mAccessibilityButtonController = new AccessibilityButtonController(
+                        AccessibilityInteractionClient.getInstance().getConnection(mConnectionId));
+            }
+            return mAccessibilityButtonController;
+        }
+    }
+
+    private void onAccessibilityButtonClicked() {
+        getAccessibilityButtonController().dispatchAccessibilityButtonClicked();
+    }
+
+    private void onAccessibilityButtonAvailabilityChanged(boolean available) {
+        getAccessibilityButtonController().dispatchAccessibilityButtonAvailabilityChanged(
+                available);
+    }
+
+    /**
      * Performs a global action. Such an action can be performed
      * at any moment regardless of the current application or user
      * location in that application. For example going back, going
@@ -1543,6 +1580,16 @@
             public void onFingerprintGesture(int gesture) {
                 AccessibilityService.this.onFingerprintGesture(gesture);
             }
+
+            @Override
+            public void onAccessibilityButtonClicked() {
+                AccessibilityService.this.onAccessibilityButtonClicked();
+            }
+
+            @Override
+            public void onAccessibilityButtonAvailabilityChanged(boolean available) {
+                AccessibilityService.this.onAccessibilityButtonAvailabilityChanged(available);
+            }
         });
     }
 
@@ -1565,6 +1612,8 @@
         private static final int DO_GESTURE_COMPLETE = 9;
         private static final int DO_ON_FINGERPRINT_ACTIVE_CHANGED = 10;
         private static final int DO_ON_FINGERPRINT_GESTURE = 11;
+        private static final int DO_ACCESSIBILITY_BUTTON_CLICKED = 12;
+        private static final int DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 13;
 
         private final HandlerCaller mCaller;
 
@@ -1645,6 +1694,17 @@
             mCaller.sendMessage(mCaller.obtainMessageI(DO_ON_FINGERPRINT_GESTURE, gesture));
         }
 
+        public void onAccessibilityButtonClicked() {
+            final Message message = mCaller.obtainMessage(DO_ACCESSIBILITY_BUTTON_CLICKED);
+            mCaller.sendMessage(message);
+        }
+
+        public void onAccessibilityButtonAvailabilityChanged(boolean available) {
+            final Message message = mCaller.obtainMessageI(
+                    DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, (available ? 1 : 0));
+            mCaller.sendMessage(message);
+        }
+
         @Override
         public void executeMessage(Message message) {
             switch (message.what) {
@@ -1750,6 +1810,15 @@
                     mCallback.onFingerprintGesture(message.arg1);
                 } return;
 
+                case (DO_ACCESSIBILITY_BUTTON_CLICKED): {
+                    mCallback.onAccessibilityButtonClicked();
+                } return;
+
+                case (DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED): {
+                    final boolean available = (message.arg1 != 0);
+                    mCallback.onAccessibilityButtonAvailabilityChanged(available);
+                } return;
+
                 default :
                     Log.w(LOG_TAG, "Unknown message type " + message.what);
             }
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 18e57cb..e135ffd 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -306,6 +306,12 @@
      */
     public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080;
 
+     /**
+     * This flag indicates to the system that the accessibility service requests that an
+     * accessibility button be shown within the system's navigation area, if available.
+     */
+    public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100;
+
     /**
      * This flag requests that all fingerprint gestures be sent to the accessibility service.
      * It is handled in {@link FingerprintGestureController}
@@ -396,6 +402,8 @@
      * @see #FLAG_REQUEST_FILTER_KEY_EVENTS
      * @see #FLAG_REPORT_VIEW_IDS
      * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS
+     * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
+     * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
      */
     public int flags;
 
@@ -631,7 +639,7 @@
      * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
      * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
      * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
-     * @see #CAPABILITY_FILTER_KEY_EVENTS
+     * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
      * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
      * @see #CAPABILITY_CAN_PERFORM_GESTURES
      */
@@ -648,7 +656,7 @@
      * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
      * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
      * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
-     * @see #CAPABILITY_FILTER_KEY_EVENTS
+     * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS
      * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
      * @see #CAPABILITY_CAN_PERFORM_GESTURES
      *
@@ -936,6 +944,8 @@
                 return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS";
             case FLAG_ENABLE_ACCESSIBILITY_VOLUME:
                 return "FLAG_ENABLE_ACCESSIBILITY_VOLUME";
+            case FLAG_REQUEST_ACCESSIBILITY_BUTTON:
+                return "FLAG_REQUEST_ACCESSIBILITY_BUTTON";
             case FLAG_CAPTURE_FINGERPRINT_GESTURES:
                 return "FLAG_CAPTURE_FINGERPRINT_GESTURES";
             default:
@@ -960,7 +970,7 @@
             case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
                 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
             case CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS:
-                return "CAPABILITY_CAN_FILTER_KEY_EVENTS";
+                return "CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS";
             case CAPABILITY_CAN_CONTROL_MAGNIFICATION:
                 return "CAPABILITY_CAN_CONTROL_MAGNIFICATION";
             case CAPABILITY_CAN_PERFORM_GESTURES:
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index 3f778ad..4e96b8f 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -50,4 +50,8 @@
     void onFingerprintCapturingGesturesChanged(boolean capturing);
 
     void onFingerprintGesture(int gesture);
+
+    void onAccessibilityButtonClicked();
+
+    void onAccessibilityButtonAvailabilityChanged(boolean available);
 }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 5499bd5..7a1931718 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -37,7 +37,8 @@
 
     boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
         long accessibilityNodeId, int interactionId,
-        IAccessibilityInteractionConnectionCallback callback, int flags, long threadId);
+        IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
+        in Bundle arguments);
 
     boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
         String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
@@ -88,6 +89,8 @@
 
     void setSoftKeyboardCallbackEnabled(boolean enabled);
 
+    boolean isAccessibilityButtonAvailable();
+
     void sendGesture(int sequence, in ParceledListSlice gestureSteps);
 
     boolean isFingerprintGestureDetectionAvailable();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 55ac1f4..558fdc6 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -637,13 +637,16 @@
     public void setCurrentFraction(float fraction) {
         initAnimation();
         fraction = clampFraction(fraction);
-        long seekTime = (long) (getScaledDuration() * fraction);
-        long currentTime = AnimationUtils.currentAnimationTimeMillis();
-        mStartTime = currentTime - seekTime;
         mStartTimeCommitted = true; // do not allow start time to be compensated for jank
-        if (!isPulsingInternal()) {
-            // If the animation loop hasn't started, the startTime will be adjusted in the first
-            // frame based on seek fraction.
+        if (isPulsingInternal()) {
+            long seekTime = (long) (getScaledDuration() * fraction);
+            long currentTime = AnimationUtils.currentAnimationTimeMillis();
+            // Only modify the start time when the animation is running. Seek fraction will ensure
+            // non-running animations skip to the correct start time.
+            mStartTime = currentTime - seekTime;
+        } else {
+            // If the animation loop hasn't started, or during start delay, the startTime will be
+            // adjusted once the delay has passed based on seek fraction.
             mSeekFraction = fraction;
         }
         mOverallFraction = fraction;
@@ -1028,7 +1031,7 @@
         // started-but-not-yet-reached-the-first-frame phase.
         mLastFrameTime = -1;
         mFirstFrameTime = -1;
-        addAnimationCallback((long) (mStartDelay * sDurationScale));
+        addAnimationCallback(0);
 
         if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
             // If there's no start delay, init the animation and notify start listeners right away
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6f95309..6a1e74e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -49,7 +49,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -74,8 +73,6 @@
 import android.os.StrictMode;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.service.autofill.AutoFillService;
-import android.service.autofill.IAutoFillAppCallback;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -116,7 +113,6 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillManager;
 import android.view.autofill.AutoFillSession;
 import android.widget.AdapterView;
@@ -127,7 +123,6 @@
 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;
@@ -1700,16 +1695,21 @@
     }
 
     /**
-     * Lazily gets the {@link IAutoFillAppCallback} for this activitity.
-     *
-     * <p>This callback is used by the {@link AutoFillService} app to auto-fill the activity fields.
+     * Lazily attachs the activity to the current {@link AutoFillSession} (if any).
      */
-    IAutoFillAppCallback getAutoFillCallback() {
+    void attachToAutoFillSession() {
         synchronized (this) {
             if (mAutoFillSession == null) {
-                mAutoFillSession = new AutoFillSession(this);
+                final AutoFillManager afm = getSystemService(AutoFillManager.class);
+                if (afm != null) {
+                    mAutoFillSession = afm.getSession();
+                    if (mAutoFillSession != null) {
+                        mAutoFillSession.attachActivity(this);
+                    } else {
+                        Log.w(TAG, "attachToAutoFillSession(): not in a session");
+                    }
+                }
             }
-            return mAutoFillSession.getCallback();
         }
     }
 
@@ -1798,6 +1798,10 @@
         getApplication().dispatchActivityStopped(this);
         mTranslucentCallback = null;
         mCalled = true;
+        if (mAutoFillSession != null && isFinishing()) {
+            mAutoFillSession.finishSession();
+            mAutoFillSession = null;
+        }
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index e848080..89510d9 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -154,12 +154,6 @@
     public abstract List<IBinder> getTopVisibleActivities();
 
     /**
-     * Returns the top, focused activity of the currently visible stack, but only if it belongs to
-     * the given UID.
-     */
-    public abstract IBinder getTopVisibleActivity(int uid);
-
-    /**
      * Callback for window manager to let activity manager know that docked stack changes its
      * minimized state.
      */
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 04510da..0b9479d 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -33,6 +33,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.util.Pair;
 import android.util.Slog;
@@ -1342,7 +1343,7 @@
                 + mStartY + ", mWidth=" + mWidth + ", mHeight=" + mHeight;
     }
 
-    private static class HideWindowListener extends Transition.TransitionListenerAdapter
+    private static class HideWindowListener extends TransitionListenerAdapter
         implements ExitTransitionCoordinator.HideSharedElementsCallback {
         private final Window mWindow;
         private final ExitTransitionCoordinator mExit;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d5371f8..dffd81f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2931,7 +2931,7 @@
             if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL || forAutoFill) {
                 structure = new AssistStructure(r.activity, forAutoFill);
                 Intent activityIntent = r.activity.getIntent();
-                boolean addAutoFillCallback = false;
+                boolean attachToSession = 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)
                 boolean notSecure = r.window == null ||
@@ -2939,7 +2939,7 @@
                                 & WindowManager.LayoutParams.FLAG_SECURE) == 0;
                 if (activityIntent != null && notSecure) {
                     if (forAutoFill) {
-                        addAutoFillCallback = true;
+                        attachToSession = true;
                     } else {
                         Intent intent = new Intent(activityIntent);
                         intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
@@ -2953,18 +2953,13 @@
                     } else {
                         // activityIntent is unlikely to be null, but if it is, we should still
                         // set the auto-fill callback.
-                        addAutoFillCallback = notSecure;
+                        attachToSession = notSecure;
                     }
                 }
                 if (!forAutoFill) {
                     r.activity.onProvideAssistContent(content);
-                } else if (addAutoFillCallback) {
-                    IAutoFillAppCallback cb = r.activity.getAutoFillCallback();
-                    if (cb != null) {
-                        data.putBinder(AutoFillService.KEY_CALLBACK, cb.asBinder());
-                    } else {
-                        Slog.w(TAG, "handleRequestAssistContextExtras(): callback was GCed");
-                    }
+                } else if (attachToSession) {
+                    r.activity.attachToAutoFillSession();
                 }
             }
         }
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 1eaf029..a512350 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -24,6 +24,7 @@
 import android.os.Parcelable;
 import android.os.ResultReceiver;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionSet;
 import android.transition.Visibility;
 import android.util.ArrayMap;
@@ -916,7 +917,7 @@
 
     protected void onTransitionsComplete() {}
 
-    protected class ContinueTransitionListener extends Transition.TransitionListenerAdapter {
+    protected class ContinueTransitionListener extends TransitionListenerAdapter {
         @Override
         public void onTransitionStart(Transition transition) {
             mIsStartingTransition = false;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9db2b92..16989c0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1896,7 +1896,7 @@
                 pi.getResDir(),
                 pi.getSplitResDirs(),
                 pi.getOverlayDirs(),
-                pi.getSharedLibraries(),
+                pi.getApplicationInfo().sharedLibraryFiles,
                 displayId,
                 overrideConfig,
                 compatInfo,
@@ -2180,7 +2180,7 @@
                 packageInfo.getResDir(),
                 splitDirs,
                 packageInfo.getOverlayDirs(),
-                packageInfo.getSharedLibraries(),
+                packageInfo.getApplicationInfo().sharedLibraryFiles,
                 displayId,
                 overrideConfiguration,
                 compatInfo,
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 0454acb..445b687 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -26,6 +26,7 @@
 import android.os.ResultReceiver;
 import android.text.TextUtils;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
 import android.view.View;
@@ -491,7 +492,7 @@
                 sharedElementTransitionStarted();
                 sharedElementTransitionComplete();
             } else {
-                sharedElementTransition.addListener(new Transition.TransitionListenerAdapter() {
+                sharedElementTransition.addListener(new TransitionListenerAdapter() {
                     @Override
                     public void onTransitionStart(Transition transition) {
                         sharedElementTransitionStarted();
@@ -592,7 +593,7 @@
                 });
                 mBackgroundAnimator.start();
             } else if (transition != null) {
-                transition.addListener(new Transition.TransitionListenerAdapter() {
+                transition.addListener(new TransitionListenerAdapter() {
                     @Override
                     public void onTransitionEnd(Transition transition) {
                         transition.removeListener(this);
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index f04eef2..29e10d8 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -31,6 +31,7 @@
 import android.os.Message;
 import android.os.ResultReceiver;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.view.View;
 import android.view.ViewGroup;
@@ -161,7 +162,7 @@
 
     private void startSharedElementExit(final ViewGroup decorView) {
         Transition transition = getSharedElementExitTransition();
-        transition.addListener(new Transition.TransitionListenerAdapter() {
+        transition.addListener(new TransitionListenerAdapter() {
             @Override
             public void onTransitionEnd(Transition transition) {
                 transition.removeListener(this);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 4f68ec7..b7c0737 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2077,8 +2077,6 @@
             } else {
                 record.trackAddedFragmentsInPop(mTmpAddedFragments);
             }
-            final int bumpAmount = isPop ? -1 : 1;
-            record.bumpBackStackNesting(bumpAmount);
             addToBackStack = addToBackStack || record.mAddToBackStack;
         }
         mTmpAddedFragments.clear();
@@ -2281,8 +2279,10 @@
             final BackStackRecord record = records.get(i);
             final boolean isPop = isRecordPop.get(i);
             if (isPop) {
+                record.bumpBackStackNesting(-1);
                 record.executePopOps();
             } else {
+                record.bumpBackStackNesting(1);
                 record.executeOps();
             }
         }
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index 2570d92..f62ab8d 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -18,6 +18,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.transition.TransitionSet;
 import android.util.ArrayMap;
@@ -332,7 +333,7 @@
             OneShotPreDrawListener.add(exitingFragment.mContainer, () -> {
                 setViewVisibility(exitingViews, View.INVISIBLE);
             });
-            exitTransition.addListener(new Transition.TransitionListenerAdapter() {
+            exitTransition.addListener(new TransitionListenerAdapter() {
                 @Override
                 public void onTransitionEnd(Transition transition) {
                     transition.removeListener(this);
@@ -995,7 +996,7 @@
             final Transition enterTransition, final ArrayList<View> enteringViews,
             final Transition exitTransition, final ArrayList<View> exitingViews,
             final TransitionSet sharedElementTransition, final ArrayList<View> sharedElementsIn) {
-        overalTransition.addListener(new Transition.TransitionListenerAdapter() {
+        overalTransition.addListener(new TransitionListenerAdapter() {
             @Override
             public void onTransitionStart(Transition transition) {
                 if (enterTransition != null) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 99ae96d..c842f78 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -585,7 +585,7 @@
     void unregisterTaskStackListener(ITaskStackListener listener);
     void moveStackToDisplay(int stackId, int displayId);
     boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
-            int resultCode, in IBinder activityToken);
+                                in IBinder activityToken);
     void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
     int restartUserInBackground(int userId);
 
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 17f5edd..7ed96af 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -311,7 +311,7 @@
                 }
 
                 mResources = ResourcesManager.getInstance().getResources(null, mResDir,
-                        splitPaths, mOverlayDirs, mSharedLibraries,
+                        splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
                         Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
                         getClassLoader());
             }
@@ -923,10 +923,6 @@
         return mOverlayDirs;
     }
 
-    public String[] getSharedLibraries() {
-        return mSharedLibraries;
-    }
-
     public String getDataDir() {
         return mDataDir;
     }
@@ -958,7 +954,7 @@
             }
 
             mResources = ResourcesManager.getInstance().getResources(null, mResDir,
-                    splitPaths, mOverlayDirs, mSharedLibraries,
+                    splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
                     Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
                     getClassLoader());
         }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2c1cdd6..44e328e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -28,6 +28,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ShortcutInfo;
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -223,13 +224,11 @@
      * superimposed over the icon in the status bar. Starting with
      * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, the template used by
      * {@link Notification.Builder} has displayed the number in the expanded notification view.
+     * Starting with {@link android.os.Build.VERSION_CODES#O}, the number may be displayed as a
+     * badge icon in Launchers that support badging.
      *
-     * If the number is 0 or negative, it is never shown.
-     *
-     * @deprecated this number is not shown anymore
      */
-    @Deprecated
-    public int number;
+    public int number = 1;
 
     /**
      * The intent to execute when the expanded status entry is clicked.  If
@@ -634,9 +633,10 @@
 
     /**
      * Special value of {@link #color} used as a place holder for an invalid color.
+     * @hide
      */
     @ColorInt
-    private static final int COLOR_INVALID = 1;
+    public static final int COLOR_INVALID = 1;
 
     /**
      * Sphere of visibility of this notification, which affects how and when the SystemUI reveals
@@ -1074,6 +1074,26 @@
     private String mChannelId;
     private long mTimeout;
 
+    private String mShortcutId;
+
+    /**
+     * If this notification is being shown as a badge, always show as a number.
+     */
+    public static final int BADGE_ICON_NONE = 0;
+
+    /**
+     * If this notification is being shown as a badge, use the {@link #getSmallIcon()} to
+     * represent this notification.
+     */
+    public static final int BADGE_ICON_SMALL = 1;
+
+    /**
+     * If this notification is being shown as a badge, use the {@link #getLargeIcon()} to
+     * represent this notification.
+     */
+    public static final int BADGE_ICON_LARGE = 2;
+    private int mBadgeIcon = BADGE_ICON_LARGE;
+
     /**
      * Structure to encapsulate a named action that can be shown as part of this notification.
      * It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is
@@ -1818,6 +1838,12 @@
             mChannelId = parcel.readString();
         }
         mTimeout = parcel.readLong();
+
+        if (parcel.readInt() != 0) {
+            mShortcutId = parcel.readString();
+        }
+
+        mBadgeIcon = parcel.readInt();
     }
 
     @Override
@@ -2042,7 +2068,7 @@
         }
         try {
             // IMPORTANT: Add marshaling code in writeToParcelImpl as we
-            // want to intercept all pending events written to the pacel.
+            // want to intercept all pending events written to the parcel.
             writeToParcelImpl(parcel, flags);
             // Must be written last!
             parcel.writeArraySet(allPendingIntents);
@@ -2185,6 +2211,15 @@
             parcel.writeInt(0);
         }
         parcel.writeLong(mTimeout);
+
+        if (mShortcutId != null) {
+            parcel.writeInt(1);
+            parcel.writeString(mShortcutId);
+        } else {
+            parcel.writeInt(0);
+        }
+
+        parcel.writeInt(mBadgeIcon);
     }
 
     /**
@@ -2382,13 +2417,30 @@
     }
 
     /**
-     * Returns the time at which this notification should be canceled, if it's not canceled already.
+     * Returns the time at which this notification should be canceled by the system, if it's not
+     * canceled already.
      */
     public long getTimeout() {
         return mTimeout;
     }
 
     /**
+     * Returns what icon should be shown for this notification if it is being displayed in a
+     * Launcher that supports badging. Will be one of {@link #BADGE_ICON_NONE},
+     * {@link #BADGE_ICON_SMALL}, or {@link #BADGE_ICON_LARGE}.
+     */
+    public int getBadgeIcon() {
+        return mBadgeIcon;
+    }
+
+    /**
+     * Returns the {@link ShortcutInfo#getId() id} that this notification supersedes, if any.
+     */
+    public String getShortcutId() {
+        return mShortcutId;
+    }
+
+    /**
      * The small icon representing this notification in the status bar and content view.
      *
      * @return the small icon representing this notification.
@@ -2483,7 +2535,6 @@
         private NotificationColorUtil mColorUtil;
         private boolean mIsLegacy;
         private boolean mIsLegacyInitialized;
-        private boolean mColorUtilInited = false;
 
         /**
          * Caches a contrast-enhanced version of {@link #mCachedContrastColorIsFor}.
@@ -2601,16 +2652,42 @@
         }
 
         private NotificationColorUtil getColorUtil() {
-            if (!mColorUtilInited) {
-                mColorUtilInited = true;
-                if (isLegacy() || isColorized()) {
-                    mColorUtil = NotificationColorUtil.getInstance(mContext);
-                }
+            if (mColorUtil == null) {
+                mColorUtil = NotificationColorUtil.getInstance(mContext);
             }
             return mColorUtil;
         }
 
         /**
+         * If this notification is duplicative of a Launcher shortcut, sets the
+         * {@link ShortcutInfo#getId() id} of the shortcut, in case the Launcher wants to hide
+         * the shortcut.
+         *
+         * This field will be ignored by Launchers that don't support badging or
+         * {@link android.content.pm.ShortcutManager shortcuts}.
+         *
+         * @param shortcutId the {@link ShortcutInfo#getId() id} of the shortcut this notification
+         *                   supersedes
+         */
+        public Builder setShortcutId(String shortcutId) {
+            mN.mShortcutId = shortcutId;
+            return this;
+        }
+
+        /**
+         * Sets which icon to display as a badge for this notification.
+         *
+         * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
+         * {@link #BADGE_ICON_LARGE}.
+         *
+         * Note: This value might be ignored, for launchers that don't support badge icons.
+         */
+        public Builder chooseBadgeIcon(int icon) {
+            mN.mBadgeIcon = icon;
+            return this;
+        }
+
+        /**
          * Specifies the channel the notification should be delivered on.
          */
         public Builder setChannel(String channelId) {
@@ -2805,13 +2882,9 @@
         }
 
         /**
-         * Set the large number at the right-hand side of the notification.  This is
-         * equivalent to setContentInfo, although it might show the number in a different
-         * font size for readability.
-         *
-         * @deprecated this number is not shown anywhere anymore
+         * Sets the number of items this notification represents. May be displayed as a badge count
+         * for Launchers that support badging.
          */
-        @Deprecated
         public Builder setNumber(int number) {
             mN.number = number;
             return this;
@@ -3096,12 +3169,16 @@
          * Set whether this notification should be colorized. When set, the color set with
          * {@link #setColor(int)} will be used as the background color of this notification.
          * <p>
-         * The coloring will only be applied if the notification is ongoing.
          * This should only be used for high priority ongoing tasks like navigation, an ongoing
          * call, or other similarly high-priority events for the user.
+         * <p>
+         * For most styles, the coloring will only be applied if the notification is ongoing.
+         * However, for {@link MediaStyle} and {@link DecoratedMediaCustomViewStyle} notifications
+         * that have a media session attached there is no requirement for it to be ongoing.
          *
          * @see Builder#setOngoing(boolean)
          * @see Builder#setColor(int)
+         * @see MediaStyle#setMediaSession(MediaSession.Token)
          */
         public Builder setColorized(boolean colorize) {
             mN.extras.putBoolean(EXTRA_COLORIZED, colorize);
@@ -3682,13 +3759,21 @@
         }
 
         private void bindExpandButton(RemoteViews contentView) {
-            int color = isColorized() ? getPrimaryTextColor() : resolveContrastColor();
+            int color = getPrimaryHighlightColor();
             contentView.setDrawableParameters(R.id.expand_button, false, -1, color,
                     PorterDuff.Mode.SRC_ATOP, -1);
             contentView.setInt(R.id.notification_header, "setOriginalNotificationColor",
                     color);
         }
 
+        /**
+         * @return the color that is used as the first primary highlight color. This is applied
+         * in several places like the action buttons or the app name in the header.
+         */
+        private int getPrimaryHighlightColor() {
+            return isColorized() ? getPrimaryTextColor() : resolveContrastColor();
+        }
+
         private void bindHeaderChronometerAndTime(RemoteViews contentView) {
             if (showsTimeOrChronometer()) {
                 contentView.setViewVisibility(R.id.time_divider, View.VISIBLE);
@@ -4265,7 +4350,7 @@
         }
 
         private CharSequence processLegacyText(CharSequence charSequence) {
-            if (isLegacy() || isColorized()) {
+            if (isLegacy() || textColorsNeedInversion()) {
                 return getColorUtil().invertCharSequenceColors(charSequence);
             } else {
                 return charSequence;
@@ -4278,7 +4363,7 @@
         private void processSmallIconColor(Icon smallIcon, RemoteViews contentView,
                 boolean ambient) {
             boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
-            int color = ambient ? resolveAmbientColor() : resolveContrastColor();
+            int color = ambient ? resolveAmbientColor() : getPrimaryHighlightColor();
             if (colorable) {
                 contentView.setDrawableParameters(R.id.icon, false, -1, color,
                         PorterDuff.Mode.SRC_ATOP, -1);
@@ -4539,6 +4624,15 @@
         private boolean isColorized() {
             return mN.isColorized();
         }
+
+        private boolean textColorsNeedInversion() {
+            if (mStyle == null || !MediaStyle.class.equals(mStyle.getClass())) {
+                return false;
+            }
+            int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+            return targetSdkVersion > Build.VERSION_CODES.M
+                    && targetSdkVersion < Build.VERSION_CODES.O;
+        }
     }
 
     /**
@@ -4551,6 +4645,14 @@
     }
 
     /**
+     * @return whether this notification has a media session attached
+     * @hide
+     */
+    public boolean hasMediaSession() {
+        return extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null;
+    }
+
+    /**
      * @return the style class of this notification
      * @hide
      */
@@ -4564,12 +4666,23 @@
     }
 
     /**
-     * @return true if this notification is colorized. This also factors in wheather the
+     * @return true if this notification is colorized. This also factors in whether the
      * notification is ongoing.
      *
      * @hide
      */
     public boolean isColorized() {
+        Class<? extends Style> style = getNotificationStyle();
+        if (MediaStyle.class.equals(style)) {
+            Boolean colorized = (Boolean) extras.get(EXTRA_COLORIZED);
+            if ((colorized == null || colorized) && hasMediaSession()) {
+                return true;
+            }
+        } else if (DecoratedMediaCustomViewStyle.class.equals(style)) {
+            if (extras.getBoolean(EXTRA_COLORIZED) && hasMediaSession()) {
+                return true;
+            }
+        }
         return extras.getBoolean(EXTRA_COLORIZED) && isOngoing();
     }
 
@@ -5815,21 +5928,27 @@
      * shown as icon-only pushbuttons, suitable for transport controls. The Bitmap given to
      * {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap) setLargeIcon()} will be
      * treated as album artwork.
-     *
+     * <p>
      * Unlike the other styles provided here, MediaStyle can also modify the standard-size
      * {@link Notification#contentView}; by providing action indices to
      * {@link #setShowActionsInCompactView(int...)} you can promote up to 3 actions to be displayed
      * in the standard view alongside the usual content.
-     *
+     * <p>
      * Notifications created with MediaStyle will have their category set to
      * {@link Notification#CATEGORY_TRANSPORT CATEGORY_TRANSPORT} unless you set a different
      * category using {@link Notification.Builder#setCategory(String) setCategory()}.
-     *
+     * <p>
      * Finally, if you attach a {@link android.media.session.MediaSession.Token} using
      * {@link android.app.Notification.MediaStyle#setMediaSession(MediaSession.Token)},
      * the System UI can identify this as a notification representing an active media session
      * and respond accordingly (by showing album artwork in the lockscreen, for example).
      *
+     * <p>
+     * Starting at {@link android.os.Build.VERSION_CODES#O Android O} any notification that has a
+     * media session attached with {@link #setMediaSession(MediaSession.Token)} will be colorized.
+     * You can opt-out of this behavior by using {@link Notification.Builder#setColorized(boolean)}.
+     * <p>
+     *
      * To use this style with your Notification, feed it to
      * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
      * <pre class="prettyprint">
@@ -5844,6 +5963,7 @@
      * </pre>
      *
      * @see Notification#bigContentView
+     * @see Notification.Builder#setColorized(boolean)
      */
     public static class MediaStyle extends Style {
         static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 3;
@@ -5981,7 +6101,7 @@
 
                     final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]);
                     final RemoteViews button = generateMediaActionButton(action,
-                            mBuilder.resolveContrastColor());
+                            getPrimaryHighlightColor());
                     view.addView(com.android.internal.R.id.media_actions, button);
                 }
             }
@@ -5995,6 +6115,10 @@
             return view;
         }
 
+        private int getPrimaryHighlightColor() {
+            return mBuilder.getPrimaryHighlightColor();
+        }
+
         private RemoteViews makeMediaBigContentView() {
             final int actionCount = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS);
             // Dont add an expanded view if there is no more content to be revealed
@@ -6012,7 +6136,7 @@
                 big.removeAllViews(com.android.internal.R.id.media_actions);
                 for (int i = 0; i < actionCount; i++) {
                     final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i),
-                            mBuilder.resolveContrastColor());
+                            getPrimaryHighlightColor());
                     big.addView(com.android.internal.R.id.media_actions, button);
                 }
             }
@@ -6157,7 +6281,10 @@
      * {@link android.app.Notification.Builder#setCustomBigContentView(RemoteViews)} and
      * {@link android.app.Notification.Builder#setCustomHeadsUpContentView(RemoteViews)} to set the
      * corresponding custom views to display.
-     *
+     * <p>
+     * Contrary to {@link MediaStyle} a developer has to opt-in to the colorizing of the
+     * notification by using {@link Notification.Builder#setColorized(boolean)}.
+     * <p>
      * To use this style with your Notification, feed it to
      * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
      * <pre class="prettyprint">
diff --git a/core/java/android/app/RemoteAction.java b/core/java/android/app/RemoteAction.java
index a37680f..5958bc1 100644
--- a/core/java/android/app/RemoteAction.java
+++ b/core/java/android/app/RemoteAction.java
@@ -35,55 +35,30 @@
  */
 public final class RemoteAction implements Parcelable {
 
-    /**
-     * Interface definition for a callback to be invoked when an action is invoked.
-     */
-    public interface OnActionListener {
-        /**
-         * Called when the associated action is invoked.
-         *
-         * @param action The action that was invoked.
-         */
-        void onAction(RemoteAction action);
-    }
-
     private static final String TAG = "RemoteAction";
 
-    private static final int MESSAGE_ACTION_INVOKED = 1;
-
     private final Icon mIcon;
     private final CharSequence mTitle;
     private final CharSequence mContentDescription;
-    private OnActionListener mActionCallback;
-    private final Messenger mMessenger;
+    private final PendingIntent mActionIntent;
 
     RemoteAction(Parcel in) {
         mIcon = Icon.CREATOR.createFromParcel(in);
         mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
         mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-        mMessenger = in.readParcelable(Messenger.class.getClassLoader());
+        mActionIntent = PendingIntent.CREATOR.createFromParcel(in);
     }
 
     public RemoteAction(@NonNull Icon icon, @NonNull CharSequence title,
-            @NonNull CharSequence contentDescription, @NonNull OnActionListener callback) {
-        if (icon == null || title == null || contentDescription == null || callback == null) {
+            @NonNull CharSequence contentDescription, @NonNull PendingIntent intent) {
+        if (icon == null || title == null || contentDescription == null || intent == null) {
             throw new IllegalArgumentException("Expected icon, title, content description and " +
                     "action callback");
         }
         mIcon = icon;
         mTitle = title;
         mContentDescription = contentDescription;
-        mActionCallback = callback;
-        mMessenger = new Messenger(new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                    case MESSAGE_ACTION_INVOKED:
-                        mActionCallback.onAction(RemoteAction.this);
-                        break;
-                }
-            }
-        });
+        mActionIntent = intent;
     }
 
     /**
@@ -108,22 +83,15 @@
     }
 
     /**
-     * Sends a message that the action was invoked.
-     * @hide
+     * Return the action intent.
      */
-    public void sendActionInvoked() {
-        Message m = Message.obtain();
-        m.what = MESSAGE_ACTION_INVOKED;
-        try {
-            mMessenger.send(m);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Could not send action-invoked", e);
-        }
+    public @NonNull PendingIntent getActionIntent() {
+        return mActionIntent;
     }
 
     @Override
     public RemoteAction clone() {
-        return new RemoteAction(mIcon, mTitle, mContentDescription, mActionCallback);
+        return new RemoteAction(mIcon, mTitle, mContentDescription, mActionIntent);
     }
 
     @Override
@@ -136,7 +104,7 @@
         mIcon.writeToParcel(out, 0);
         TextUtils.writeToParcel(mTitle, out, flags);
         TextUtils.writeToParcel(mContentDescription, out, flags);
-        out.writeParcelable(mMessenger, flags);
+        mActionIntent.writeToParcel(out, flags);
     }
 
     public void dump(String prefix, PrintWriter pw) {
@@ -144,6 +112,7 @@
         pw.print("title=" + mTitle);
         pw.print(" contentDescription=" + mContentDescription);
         pw.print(" icon=" + mIcon);
+        pw.print(" action=" + mActionIntent.getIntent());
         pw.println();
     }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5a75a67..44db326 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -30,6 +30,8 @@
 import android.app.usage.UsageStatsManager;
 import android.appwidget.AppWidgetManager;
 import android.bluetooth.BluetoothManager;
+import android.companion.CompanionDeviceManager;
+import android.companion.ICompanionDeviceManager;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.IRestrictionsManager;
@@ -115,6 +117,7 @@
 import android.service.autofill.IAutoFillManagerService;
 import android.service.persistentdata.IPersistentDataBlockService;
 import android.service.persistentdata.PersistentDataBlockManager;
+import android.service.vr.IVrManager;
 import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
@@ -633,6 +636,18 @@
                         UserHandle.getAppId(Process.myUid()));
             }});
 
+        registerService(Context.COMPANION_DEVICE_SERVICE, CompanionDeviceManager.class,
+                new CachedServiceFetcher<CompanionDeviceManager>() {
+                    @Override
+                    public CompanionDeviceManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        IBinder iBinder =
+                                ServiceManager.getServiceOrThrow(Context.COMPANION_DEVICE_SERVICE);
+                        ICompanionDeviceManager service =
+                                ICompanionDeviceManager.Stub.asInterface(iBinder);
+                        return new CompanionDeviceManager(service, ctx);
+                    }});
+
         registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class,
                 new CachedServiceFetcher<ConsumerIrManager>() {
             @Override
@@ -814,6 +829,14 @@
                 IAutoFillManagerService service = IAutoFillManagerService.Stub.asInterface(b);
                 return new AutoFillManager(ctx, service);
             }});
+
+        registerService(Context.VR_SERVICE, VrManager.class, new CachedServiceFetcher<VrManager>() {
+            @Override
+            public VrManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.VR_SERVICE);
+                return new VrManager(IVrManager.Stub.asInterface(b));
+            }
+        });
     }
 
     /**
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 3f467a0..b219f2a 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -145,14 +145,25 @@
     }
 
     @Override
+    public void show() {
+        super.show();
+        getButton(BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if (mTimePicker.validateInput()) {
+                    if (mTimeSetListener != null) {
+                        mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
+                                mTimePicker.getCurrentMinute());
+                    }
+                    dismiss();
+                }
+            }
+        });
+    }
+
+    @Override
     public void onClick(DialogInterface dialog, int which) {
         switch (which) {
-            case BUTTON_POSITIVE:
-                if (mTimeSetListener != null) {
-                    mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
-                            mTimePicker.getCurrentMinute());
-                }
-                break;
             case BUTTON_NEGATIVE:
                 cancel();
                 break;
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 6d1d1a3..1d6f42e 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1118,6 +1118,16 @@
                 public void onFingerprintGesture(int gesture) {
                     /* do nothing */
                 }
+
+                @Override
+                public void onAccessibilityButtonClicked() {
+                    /* do nothing */
+                }
+
+                @Override
+                public void onAccessibilityButtonAvailabilityChanged(boolean available) {
+                    /* do nothing */
+                }
             });
         }
     }
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
new file mode 100644
index 0000000..a0b0eea
--- /dev/null
+++ b/core/java/android/app/VrManager.java
@@ -0,0 +1,44 @@
+package android.app;
+
+
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.service.vr.IVrManager;
+
+/**
+ * Used to control aspects of a devices Virtual Reality (VR) capabilities.
+ * <p>
+ * You do not instantiate this class directly; instead, retrieve it through
+ * {@link android.content.Context#getSystemService}.
+ * @hide
+ */
+@SystemApi
+public class VrManager {
+    private final IVrManager mService;
+
+    /**
+     * {@hide}
+     */
+    public VrManager(IVrManager service) {
+        mService = service;
+    }
+
+    /**
+     * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
+     * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
+     * by VR viewers to indicate that a device is placed in a VR viewer.
+     *
+     * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
+     *
+     * @see Activity#setVrModeEnabled(boolean, ComponentName)
+     * @param enabled true if the device should be placed in persistent VR mode.
+     */
+    public void setPersistentVrModeEnabled(boolean enabled) {
+        try {
+            mService.setPersistentVrModeEnabled(enabled);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 08832d1..f1ccabe 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -377,7 +377,7 @@
      * @hide
      */
     public static final String ACTION_BUGREPORT_SHARING_ACCEPTED =
-            "com.android.server.action.BUGREPORT_SHARING_ACCEPTED";
+            "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED";
 
     /**
      * Action: Bugreport sharing with device owner has been declined by the user.
@@ -385,7 +385,7 @@
      * @hide
      */
     public static final String ACTION_BUGREPORT_SHARING_DECLINED =
-            "com.android.server.action.BUGREPORT_SHARING_DECLINED";
+            "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED";
 
     /**
      * Action: Bugreport has been collected and is dispatched to {@code DevicePolicyManagerService}.
@@ -6108,8 +6108,6 @@
      * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of
      * an affiliated user or profile.
      * @see #setLockTaskPackages
-     *
-     * @hide
      */
     public @NonNull String[] getLockTaskPackages(@NonNull ComponentName admin) {
         throwIfParentInstance("getLockTaskPackages");
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 2858991..91b87d7 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -144,8 +144,7 @@
         }
 
         /**
-         * Returns the payload contained in this log. Each call to this method will
-         * retrieve the next payload item. If no more payload exists, it returns {@code null}.
+         * Returns the payload contained in this log entry or {@code null} if there is no payload.
          */
         public Object getData() {
             return mEvent.getData();
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index a482103..176e48f 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -37,9 +37,11 @@
     public static final int SOURCE_CODEC_TYPE_APTX    = 2;
     public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
     public static final int SOURCE_CODEC_TYPE_LDAC    = 4;
+    public static final int SOURCE_CODEC_TYPE_MAX     = 5;
 
     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
 
+    public static final int CODEC_PRIORITY_DISABLED = -1;
     public static final int CODEC_PRIORITY_DEFAULT = 0;
     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
 
@@ -72,7 +74,7 @@
 
     public BluetoothCodecConfig(int codecType, int codecPriority,
                                 int sampleRate, int bitsPerSample,
-                                int channelMode,long codecSpecific1,
+                                int channelMode, long codecSpecific1,
                                 long codecSpecific2, long codecSpecific3,
                                 long codecSpecific4) {
         mCodecType = codecType;
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 17a802d..b89c64a 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -67,7 +67,9 @@
     private final byte[] mManufacturerData;
     @Nullable
     private final byte[] mManufacturerDataMask;
-    private static final ScanFilter EMPTY = new ScanFilter.Builder().build() ;
+
+    /** @hide */
+    public static final ScanFilter EMPTY = new ScanFilter.Builder().build() ;
 
 
     private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
@@ -318,8 +320,12 @@
         return true;
     }
 
-    // Check if the uuid pattern is contained in a list of parcel uuids.
-    private boolean matchesServiceUuids(ParcelUuid uuid, ParcelUuid parcelUuidMask,
+    /**
+     * Check if the uuid pattern is contained in a list of parcel uuids.
+     *
+     * @hide
+     */
+    public static boolean matchesServiceUuids(ParcelUuid uuid, ParcelUuid parcelUuidMask,
             List<ParcelUuid> uuids) {
         if (uuid == null) {
             return true;
@@ -338,7 +344,7 @@
     }
 
     // Check if the uuid pattern matches the particular service uuid.
-    private boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
+    private static boolean matchesServiceUuid(UUID uuid, UUID mask, UUID data) {
         if (mask == null) {
             return uuid.equals(data);
         }
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/companion/AssociationRequest.aidl
similarity index 68%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/android/companion/AssociationRequest.aidl
index ded8f97..6c91062 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/companion/AssociationRequest.aidl
@@ -13,18 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.autofill;
 
-import java.io.PrintWriter;
+package android.companion;
 
-final class CallbackHelper {
-
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
-
-    static interface Finalizer {
-        void gone();
-    }
-}
+parcelable AssociationRequest;
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
new file mode 100644
index 0000000..d477f43
--- /dev/null
+++ b/core/java/android/companion/AssociationRequest.java
@@ -0,0 +1,191 @@
+/*
+ * 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.companion;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.OneTimeUseBuilder;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A request for the user to select a companion device to associate with.
+ *
+ * You can optionally set a {@link Builder#setDeviceFilter filter} for which devices to show to the
+ * user to select from.
+ * The exact type and fields of the filter you can set depend on the
+ * medium type. See {@link Builder}'s static factory methods for specific protocols that are
+ * supported.
+ *
+ * You can also set {@link Builder#setSingleDevice single device} to request a popup with single
+ * device to be shown instead of a list to choose from
+ *
+ * @param <F> Device filter type
+ */
+public final class AssociationRequest<F extends DeviceFilter> implements Parcelable {
+
+    /** @hide */
+    public static final int MEDIUM_TYPE_BLUETOOTH = 0;
+    /** @hide */
+    public static final int MEDIUM_TYPE_BLUETOOTH_LE = 1;
+    /** @hide */
+    public static final int MEDIUM_TYPE_WIFI = 2;
+
+    /** @hide */
+    @IntDef({MEDIUM_TYPE_BLUETOOTH, MEDIUM_TYPE_BLUETOOTH_LE, MEDIUM_TYPE_WIFI})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MediumType {}
+
+    private final boolean mSingleDevice;
+    private final int mMediumType;
+    private final F mDeviceFilter;
+
+    private AssociationRequest(boolean singleDevice, int mMediumType, F deviceFilter) {
+        this.mSingleDevice = singleDevice;
+        this.mMediumType = mMediumType;
+        this.mDeviceFilter = deviceFilter;
+    }
+
+    private AssociationRequest(Parcel in) {
+        this(
+            in.readByte() != 0,
+            in.readInt(),
+            in.readParcelable(AssociationRequest.class.getClassLoader()));
+    }
+
+    /** @hide */
+    public boolean isSingleDevice() {
+        return mSingleDevice;
+    }
+
+    /** @hide */
+    @MediumType
+    public int getMediumType() {
+        return mMediumType;
+    }
+
+    /** @hide */
+    @Nullable
+    public F getDeviceFilter() {
+        return mDeviceFilter;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByte((byte) (mSingleDevice ? 1 : 0));
+        dest.writeInt(mMediumType);
+        dest.writeParcelable(mDeviceFilter, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<AssociationRequest> CREATOR = new Creator<AssociationRequest>() {
+        @Override
+        public AssociationRequest createFromParcel(Parcel in) {
+            return new AssociationRequest(in);
+        }
+
+        @Override
+        public AssociationRequest[] newArray(int size) {
+            return new AssociationRequest[size];
+        }
+    };
+
+    /**
+     * A builder for {@link AssociationRequest}
+     *
+     * @param <F> the type of filter for the request.
+     */
+    public static final class Builder<F extends DeviceFilter>
+            extends OneTimeUseBuilder<AssociationRequest<F>> {
+        private boolean mSingleDevice = false;
+        @MediumType private int mMediumType;
+        @Nullable private F mDeviceFilter = null;
+
+        private Builder() {}
+
+        /**
+         * Create a new builder for an association request with a Bluetooth LE device
+         */
+        @NonNull
+        public static Builder<BluetoothLEDeviceFilter> createForBluetoothLEDevice() {
+            return new Builder<BluetoothLEDeviceFilter>()
+                    .setMediumType(MEDIUM_TYPE_BLUETOOTH_LE);
+        }
+
+        /**
+         * Create a new builder for an association request with a Bluetooth(non-LE) device
+         */
+        @NonNull
+        public static Builder<BluetoothDeviceFilter> createForBluetoothDevice() {
+            return new Builder<BluetoothDeviceFilter>()
+                    .setMediumType(MEDIUM_TYPE_BLUETOOTH);
+        }
+
+        //TODO implement, once specific filter classes are available
+//        public static Builder<> createForWiFiDevice()
+//        public static Builder<> createForNanDevice()
+
+        /**
+         * @param singleDevice if true, scanning for a device will stop as soon as at least one
+         *                     fitting device is found
+         */
+        @NonNull
+        public Builder<F> setSingleDevice(boolean singleDevice) {
+            checkNotUsed();
+            this.mSingleDevice = singleDevice;
+            return this;
+        }
+
+        /**
+         * @param deviceFilter if set, only devices matching the given filter will be shown to the
+         *                     user
+         */
+        @NonNull
+        public Builder<F> setDeviceFilter(@Nullable F deviceFilter) {
+            checkNotUsed();
+            this.mDeviceFilter = deviceFilter;
+            return this;
+        }
+
+        /**
+         * @param deviceType A type of medium over which to discover devices
+         *
+         * @see MediumType
+         */
+        @NonNull
+        private Builder<F> setMediumType(@MediumType int deviceType) {
+            mMediumType = deviceType;
+            return this;
+        }
+
+        /** @inheritDoc */
+        @NonNull
+        @Override
+        public AssociationRequest<F> build() {
+            markUsed();
+            return new AssociationRequest<>(mSingleDevice, mMediumType, mDeviceFilter);
+        }
+    }
+}
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
new file mode 100644
index 0000000..5a69955
--- /dev/null
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -0,0 +1,202 @@
+/*
+ * 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.companion;
+
+import static android.companion.BluetoothDeviceFilterUtils.matchesAddress;
+import static android.companion.BluetoothDeviceFilterUtils.matchesName;
+import static android.companion.BluetoothDeviceFilterUtils.matchesServiceUuids;
+import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
+import static android.companion.BluetoothDeviceFilterUtils.patternToString;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothDevice;
+import android.os.Parcel;
+import android.os.ParcelUuid;
+import android.provider.OneTimeUseBuilder;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * A filter for Bluetooth(non-LE) devices
+ */
+public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice> {
+
+    private static BluetoothDeviceFilter NO_OP;
+
+    private final Pattern mNamePattern;
+    private final String mAddress;
+    private final List<ParcelUuid> mServiceUuids;
+    private final List<ParcelUuid> mServiceUuidMasks;
+
+    private BluetoothDeviceFilter(
+            Pattern namePattern,
+            String address,
+            List<ParcelUuid> serviceUuids,
+            List<ParcelUuid> serviceUuidMasks) {
+        mNamePattern = namePattern;
+        mAddress = address;
+        mServiceUuids = ArrayUtils.emptyIfNull(serviceUuids);
+        mServiceUuidMasks = ArrayUtils.emptyIfNull(serviceUuidMasks);
+    }
+
+    private BluetoothDeviceFilter(Parcel in) {
+        this(
+            patternFromString(in.readString()),
+            in.readString(),
+            readUuids(in),
+            readUuids(in));
+    }
+
+    private static List<ParcelUuid> readUuids(Parcel in) {
+        final ArrayList<ParcelUuid> list = new ArrayList<>();
+        in.readParcelableList(list, ParcelUuid.class.getClassLoader());
+        return list;
+    }
+
+    /** @hide */
+    @NonNull
+    public static BluetoothDeviceFilter nullsafe(@Nullable BluetoothDeviceFilter nullable) {
+        return nullable != null ? nullable : noOp();
+    }
+
+    /** @hide */
+    @NonNull
+    public static BluetoothDeviceFilter noOp() {
+        if (NO_OP == null) NO_OP = new Builder().build();
+        return NO_OP;
+    }
+
+    /** @hide */
+    @Override
+    public boolean matches(BluetoothDevice device) {
+        return matchesAddress(mAddress, device)
+                && matchesServiceUuids(mServiceUuids, mServiceUuidMasks, device)
+                && matchesName(getNamePattern(), device);
+    }
+
+    /** @hide */
+    @Nullable
+    public Pattern getNamePattern() {
+        return mNamePattern;
+    }
+
+    /** @hide */
+    @Nullable
+    public String getAddress() {
+        return mAddress;
+    }
+
+    /** @hide */
+    @NonNull
+    public List<ParcelUuid> getServiceUuids() {
+        return mServiceUuids;
+    }
+
+    /** @hide */
+    @NonNull
+    public List<ParcelUuid> getServiceUuidMasks() {
+        return mServiceUuidMasks;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(patternToString(getNamePattern()));
+        dest.writeString(mAddress);
+        dest.writeParcelableList(mServiceUuids, flags);
+        dest.writeParcelableList(mServiceUuidMasks, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<BluetoothDeviceFilter> CREATOR
+            = new Creator<BluetoothDeviceFilter>() {
+        @Override
+        public BluetoothDeviceFilter createFromParcel(Parcel in) {
+            return new BluetoothDeviceFilter(in);
+        }
+
+        @Override
+        public BluetoothDeviceFilter[] newArray(int size) {
+            return new BluetoothDeviceFilter[size];
+        }
+    };
+
+    /**
+     * A builder for {@link BluetoothDeviceFilter}
+     */
+    public static final class Builder extends OneTimeUseBuilder<BluetoothDeviceFilter> {
+        private Pattern mNamePattern;
+        private String mAddress;
+        private ArrayList<ParcelUuid> mServiceUuid;
+        private ArrayList<ParcelUuid> mServiceUuidMask;
+
+        /**
+         * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
+         *              given regular expression will be shown
+         */
+        public Builder setNamePattern(@Nullable Pattern regex) {
+            checkNotUsed();
+            mNamePattern = regex;
+            return this;
+        }
+
+        /**
+         * @param address if set, only devices with MAC address exactly matching the given one will
+         *                pass the filter
+         */
+        @NonNull
+        public Builder setAddress(@Nullable String address) {
+            checkNotUsed();
+            mAddress = address;
+            return this;
+        }
+
+        /**
+         * Add filtering by certain bits of {@link BluetoothDevice#getUuids()}
+         *
+         * A device with any uuid matching the given bits is considered passing
+         *
+         * @param serviceUuid the values for the bits to match
+         * @param serviceUuidMask if provided, only those bits would have to match.
+         */
+        @NonNull
+        public Builder addServiceUuid(
+                @Nullable ParcelUuid serviceUuid, @Nullable ParcelUuid serviceUuidMask) {
+            checkNotUsed();
+            mServiceUuid = ArrayUtils.add(mServiceUuid, serviceUuid);
+            mServiceUuidMask = ArrayUtils.add(mServiceUuidMask, serviceUuidMask);
+            return this;
+        }
+
+        /** @inheritDoc */
+        @Override
+        @NonNull
+        public BluetoothDeviceFilter build() {
+            markUsed();
+            return new BluetoothDeviceFilter(
+                    mNamePattern, mAddress, mServiceUuid, mServiceUuidMask);
+        }
+    }
+}
diff --git a/core/java/android/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java
new file mode 100644
index 0000000..289f995
--- /dev/null
+++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java
@@ -0,0 +1,107 @@
+/*
+ * 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.companion;
+
+import static android.text.TextUtils.firstNotEmpty;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.ScanFilter;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/** @hide */
+public class BluetoothDeviceFilterUtils {
+    private BluetoothDeviceFilterUtils() {}
+
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "BluetoothDeviceFilterUtil";
+
+    @Nullable
+    static String patternToString(@Nullable Pattern p) {
+        return p == null ? null : p.pattern();
+    }
+
+    @Nullable
+    static Pattern patternFromString(@Nullable String s) {
+        return s == null ? null : Pattern.compile(s);
+    }
+
+    static boolean matches(ScanFilter filter, BluetoothDevice device) {
+        return matchesAddress(filter.getDeviceAddress(), device)
+                && matchesServiceUuid(filter.getServiceUuid(), filter.getServiceUuidMask(), device);
+    }
+
+    static boolean matchesAddress(String deviceAddress, BluetoothDevice device) {
+        final boolean result = deviceAddress == null
+                || (device == null || !deviceAddress.equals(device.getAddress()));
+        if (DEBUG) debugLogMatchResult(result, device, deviceAddress);
+        return result;
+    }
+
+    static boolean matchesServiceUuids(List<ParcelUuid> serviceUuids,
+            List<ParcelUuid> serviceUuidMasks, BluetoothDevice device) {
+        for (int i = 0; i < serviceUuids.size(); i++) {
+            ParcelUuid uuid = serviceUuids.get(i);
+            ParcelUuid uuidMask = serviceUuidMasks.get(i);
+            if (!matchesServiceUuid(uuid, uuidMask, device)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static boolean matchesServiceUuid(ParcelUuid serviceUuid, ParcelUuid serviceUuidMask,
+            BluetoothDevice device) {
+        final boolean result = serviceUuid == null ||
+                ScanFilter.matchesServiceUuids(
+                        serviceUuid,
+                        serviceUuidMask,
+                        Arrays.asList(device.getUuids()));
+        if (DEBUG) debugLogMatchResult(result, device, serviceUuid);
+        return result;
+    }
+
+    static boolean matchesName(@Nullable Pattern namePattern, BluetoothDevice device) {
+        boolean result;
+        if (namePattern == null)  {
+            result = true;
+        } else if (device == null) {
+            result = false;
+        } else {
+            final String name = device.getName();
+            result = name != null && namePattern.matcher(name).find();
+        }
+        if (DEBUG) debugLogMatchResult(result, device, namePattern);
+        return result;
+    }
+
+    private static void debugLogMatchResult(
+            boolean result, BluetoothDevice device, Object criteria) {
+        Log.i(LOG_TAG, getDeviceDisplayName(device) + (result ? " ~ " : " !~ ") + criteria);
+    }
+
+    public static String getDeviceDisplayName(@NonNull BluetoothDevice device) {
+        return firstNotEmpty(device.getAliasName(), device.getAddress());
+    }
+}
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/companion/BluetoothLEDeviceFilter.aidl
similarity index 68%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/android/companion/BluetoothLEDeviceFilter.aidl
index ded8f97..628cf7b 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/companion/BluetoothLEDeviceFilter.aidl
@@ -13,18 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.autofill;
 
-import java.io.PrintWriter;
+package android.companion;
 
-final class CallbackHelper {
-
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
-
-    static interface Finalizer {
-        void gone();
-    }
-}
+parcelable BluetoothLEDeviceFilter;
diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLEDeviceFilter.java
new file mode 100644
index 0000000..4a481ca
--- /dev/null
+++ b/core/java/android/companion/BluetoothLEDeviceFilter.java
@@ -0,0 +1,151 @@
+/*
+ * 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.companion;
+
+import static android.companion.BluetoothDeviceFilterUtils.patternFromString;
+import static android.companion.BluetoothDeviceFilterUtils.patternToString;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.ScanFilter;
+import android.os.Parcel;
+import android.provider.OneTimeUseBuilder;
+
+import com.android.internal.util.ObjectUtils;
+
+import java.util.regex.Pattern;
+
+/**
+ * A filter for Bluetooth LE devices
+ *
+ * @see ScanFilter
+ */
+public final class BluetoothLEDeviceFilter implements DeviceFilter<BluetoothDevice> {
+
+    private static BluetoothLEDeviceFilter NO_OP;
+
+    private final Pattern mNamePattern;
+    private final ScanFilter mScanFilter;
+
+    private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter) {
+        mNamePattern = namePattern;
+        mScanFilter = ObjectUtils.firstNotNull(scanFilter, ScanFilter.EMPTY);
+    }
+
+    @SuppressLint("ParcelClassLoader")
+    private BluetoothLEDeviceFilter(Parcel in) {
+        this(
+            patternFromString(in.readString()),
+            in.readParcelable(null));
+    }
+
+    /** @hide */
+    @NonNull
+    public static BluetoothLEDeviceFilter nullsafe(@Nullable BluetoothLEDeviceFilter nullable) {
+        return nullable != null ? nullable : noOp();
+    }
+
+    /** @hide */
+    @NonNull
+    public static BluetoothLEDeviceFilter noOp() {
+        if (NO_OP == null) NO_OP = new Builder().build();
+        return NO_OP;
+    }
+
+    /** @hide */
+    @Nullable
+    public Pattern getNamePattern() {
+        return mNamePattern;
+    }
+
+    /** @hide */
+    @NonNull
+    public ScanFilter getScanFilter() {
+        return mScanFilter;
+    }
+
+    /** @hide */
+    @Override
+    public boolean matches(BluetoothDevice device) {
+        return BluetoothDeviceFilterUtils.matches(getScanFilter(), device)
+                && BluetoothDeviceFilterUtils.matchesName(getNamePattern(), device);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(patternToString(getNamePattern()));
+        dest.writeParcelable(mScanFilter, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<BluetoothLEDeviceFilter> CREATOR
+            = new Creator<BluetoothLEDeviceFilter>() {
+        @Override
+        public BluetoothLEDeviceFilter createFromParcel(Parcel in) {
+            return new BluetoothLEDeviceFilter(in);
+        }
+
+        @Override
+        public BluetoothLEDeviceFilter[] newArray(int size) {
+            return new BluetoothLEDeviceFilter[size];
+        }
+    };
+
+    /**
+     * Builder for {@link BluetoothLEDeviceFilter}
+     */
+    public static final class Builder extends OneTimeUseBuilder<BluetoothLEDeviceFilter> {
+        private ScanFilter mScanFilter;
+        private Pattern mNamePattern;
+
+        /**
+         * @param regex if set, only devices with {@link BluetoothDevice#getName name} matching the
+         *              given regular expression will be shown
+         */
+        public Builder setNamePattern(@Nullable Pattern regex) {
+            checkNotUsed();
+            mNamePattern = regex;
+            return this;
+        }
+
+        /**
+         * @param scanFilter a {@link ScanFilter} to filter devices by
+         *
+         * @see ScanFilter for specific details on its various fields
+         */
+        @NonNull
+        public Builder setScanFilter(@Nullable ScanFilter scanFilter) {
+            checkNotUsed();
+            mScanFilter = scanFilter;
+            return this;
+        }
+
+        /** @inheritDoc */
+        @Override
+        @NonNull
+        public BluetoothLEDeviceFilter build() {
+            markUsed();
+            return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter);
+        }
+    }
+}
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
new file mode 100644
index 0000000..b379c7c
--- /dev/null
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -0,0 +1,141 @@
+/*
+ * 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.companion;
+
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.IntentSender;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+
+/**
+ * System level service for managing companion devices
+ *
+ * Usage:
+ * To obtain an instance call
+ * {@link Context#getSystemService}({@link Context#COMPANION_DEVICE_SERVICE})
+ *
+ * Then, call {@link #associate} to initiate the flow of associating current package
+ * with a device selected by user
+ *
+ * @see AssociationRequest
+ */
+public final class CompanionDeviceManager {
+
+    /**
+     * A device, returned in the activity result of the {@link IntentSender} received in
+     * {@link Callback#onDeviceFound}
+     */
+    public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+
+    /**
+     * A callback to receive once at least one suitable device is found, or the search failed
+     * (e.g. timed out)
+     */
+    public abstract static class Callback {
+
+        /**
+         * Called once at least one suitable device is found
+         *
+         * @param chooserLauncher a {@link IntentSender} to launch the UI for user to select a
+         *                        device
+         */
+        public abstract void onDeviceFound(IntentSender chooserLauncher);
+
+        /**
+         * Called if there was an error looking for device(s), e.g. timeout
+         *
+         * @param error the cause of the error
+         */
+        public abstract void onFailure(CharSequence error);
+    }
+
+    private final ICompanionDeviceManager mService;
+    private final Context mContext;
+
+    /** @hide */
+    public CompanionDeviceManager(
+            @NonNull ICompanionDeviceManager service, @NonNull Context context) {
+        mService = service;
+        mContext = context;
+    }
+
+    /**
+     * Associate this app with a companion device, selected by user
+     *
+     * Once at least one appropriate device is found, {@code callback} will be called with a
+     * {@link PendingIntent} that can be used to show the list of available devices for the user
+     * to select.
+     * It should be started for result (i.e. using
+     * {@link android.app.Activity#startIntentSenderForResult}), as the resulting
+     * {@link android.content.Intent} will contain extra {@link #EXTRA_DEVICE}, with the selected
+     * device. (e.g. {@link android.bluetooth.BluetoothDevice})
+     *
+     * @param request specific details about this request
+     * @param callback will be called once there's at least one device found for user to choose from
+     * @param handler A handler to control which thread the callback will be delivered on, or null,
+     *                to deliver it on main thread
+     *
+     * @see AssociationRequest
+     */
+    public void associate(
+            @NonNull AssociationRequest<?> request,
+            @NonNull Callback callback,
+            @Nullable Handler handler) {
+        final Handler finalHandler = handler != null
+                ? handler
+                : new Handler(Looper.getMainLooper());
+        try {
+            mService.associate(
+                    request,
+                    new IOnAssociateCallback.Stub() {
+
+                        @Override
+                        public void onSuccess(PendingIntent launcher) throws RemoteException {
+                            finalHandler.post(() -> {
+                                callback.onDeviceFound(launcher.getIntentSender());
+                            });
+                        }
+
+                        @Override
+                        public void onFailure(CharSequence reason) throws RemoteException {
+                            finalHandler.post(() -> callback.onFailure(reason));
+                        }
+                    },
+                    mContext.getPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    public void requestNotificationAccess() {
+        //TODO implement
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+    /** @hide */
+    public boolean haveNotificationAccess() {
+        //TODO implement
+        throw new UnsupportedOperationException("Not yet implemented");
+    }
+
+}
diff --git a/core/java/android/companion/DeviceFilter.java b/core/java/android/companion/DeviceFilter.java
new file mode 100644
index 0000000..8362b2d
--- /dev/null
+++ b/core/java/android/companion/DeviceFilter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.companion;
+
+import android.annotation.Nullable;
+import android.os.Parcelable;
+
+/**
+ * A filter for companion devices of type {@code D}
+ *
+ * @param <D> Type of devices, filtered by this filter,
+ *           e.g. {@link android.bluetooth.BluetoothDevice}, {@link android.net.wifi.WifiInfo}
+ */
+public interface DeviceFilter<D extends Parcelable> extends Parcelable {
+
+    /**
+     * @return whether the given device matches this filter
+     *
+     * @hide
+     */
+    boolean matches(D device);
+
+    /**
+     * A nullsafe {@link #matches(Parcelable)}, returning true if the filter is null
+     *
+     * @hide
+     */
+    static <D extends Parcelable> boolean matches(@Nullable DeviceFilter<D> filter, D device) {
+        return filter == null || filter.matches(device);
+    }
+}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
new file mode 100644
index 0000000..065e31b
--- /dev/null
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.companion;
+
+import android.companion.IOnAssociateCallback;
+import android.companion.AssociationRequest;
+
+/**
+ * Interface for communication with the core companion device manager service.
+ *
+ * @hide
+ */
+interface ICompanionDeviceManager {
+    void associate(in AssociationRequest request,
+        in IOnAssociateCallback callback,
+        in String callingPackage); //TODO int userId?
+
+    //TODO add these
+//    boolean haveNotificationAccess(String packageName);
+//    oneway void requestNotificationAccess(String packageName);
+}
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/companion/ICompanionDeviceManagerService.aidl
similarity index 65%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/android/companion/ICompanionDeviceManagerService.aidl
index ded8f97..ff2a7eb 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/companion/ICompanionDeviceManagerService.aidl
@@ -13,18 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.autofill;
 
-import java.io.PrintWriter;
+package android.companion;
 
-final class CallbackHelper {
+import android.companion.AssociationRequest;
+import android.companion.IOnAssociateCallback;
 
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
 
-    static interface Finalizer {
-        void gone();
-    }
+/** @hide */
+interface ICompanionDeviceManagerService {
+    void startDiscovery(
+        in AssociationRequest request,
+        in IOnAssociateCallback callback,
+        in String callingPackage);
 }
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
similarity index 60%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
index ded8f97..c9dd345 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
@@ -10,21 +10,15 @@
  * 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
+ * See the License for the specific language governing per  missions and
  * limitations under the License.
  */
-package android.service.autofill;
 
-import java.io.PrintWriter;
+package android.companion;
 
-final class CallbackHelper {
+import android.bluetooth.BluetoothDevice;
 
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
-
-    static interface Finalizer {
-        void gone();
-    }
+/** @hide */
+interface ICompanionDeviceManagerServiceCallback {
+    void onDeviceSelected(in BluetoothDevice device);
 }
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/companion/IOnAssociateCallback.aidl
similarity index 60%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/android/companion/IOnAssociateCallback.aidl
index ded8f97..4867eadd 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/companion/IOnAssociateCallback.aidl
@@ -10,21 +10,16 @@
  * 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
+ * See the License for the specific language governing per  missions and
  * limitations under the License.
  */
-package android.service.autofill;
 
-import java.io.PrintWriter;
+package android.companion;
 
-final class CallbackHelper {
+import android.app.PendingIntent;
 
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
-
-    static interface Finalizer {
-        void gone();
-    }
+/** @hide */
+interface IOnAssociateCallback {
+    void onSuccess(in PendingIntent launcher);
+    void onFailure(in CharSequence reason);
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f610a29..06f7303 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -35,6 +35,7 @@
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.Notification;
+import android.app.VrManager;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
@@ -3599,6 +3600,14 @@
     public static final String PRINT_SERVICE = "print";
 
     /**
+     * {@link android.companion.CompanionDeviceManager} for managing companion devices
+     *
+     * @see #getSystemService
+     * @see android.companion.CompanionDeviceManager
+     */
+    public static final String COMPANION_DEVICE_SERVICE = "companion_device";
+
+    /**
      * Use with {@link #getSystemService} to retrieve a
      * {@link android.hardware.ConsumerIrManager} for transmitting infrared
      * signals from the device.
@@ -3764,6 +3773,16 @@
     public static final String OVERLAY_SERVICE = "overlay";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link VrManager} for accessing the VR service.
+     *
+     * @see #getSystemService
+     * @hide
+     */
+    @SystemApi
+    public static final String VR_SERVICE = "vrmanager";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 1130327..6a8141f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1806,6 +1806,41 @@
     @SystemApi
     public static final String EXTRA_PERMISSION_NAME = "android.intent.extra.PERMISSION_NAME";
 
+    /**
+     * Intent extra: An id if an autofill item ({@link
+     * android.view.autofill.Dataset} or {@link android.view.autofill.FillResponse}).
+     * <p>
+     * Type: String
+     * </p>
+     */
+    public static final String EXTRA_AUTO_FILL_ITEM_ID = "android.intent.extra.AUTO_FILL_ITEM_ID";
+
+    /**
+     * Intent extra: The assist structure which captures the filled screen.
+     * <p>
+     * Type: {@link android.app.assist.AssistStructure}
+     * </p>
+     */
+    public static final String EXTRA_AUTO_FILL_ASSIST_STRUCTURE =
+            "android.intent.extra.AUTO_FILL_ASSIST_STRUCTURE";
+
+    /**
+     * Intent extra: The metadata associated with the authenticated entity ({@link
+     * android.view.autofill.Dataset} or {@link android.view.autofill.FillResponse}).
+     * <p>
+     * Type: {@link android.os.Bundle}
+     * </p>
+     */
+    public static final String EXTRA_AUTO_FILL_EXTRAS = "android.intent.extra.AUTO_FILL_EXTRAS";
+
+    /**
+     * Intent extra: A callback to report an authentication result.
+     * <p>
+     * Type: {@link android.view.autofill.FillResponse}
+     * </p>
+     */
+    public static final String EXTRA_AUTO_FILL_CALLBACK = "android.intent.extra.AUTO_FILL_CALLBACK";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent broadcast actions (see action variable).
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index dd53eac..74d2f11 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -351,7 +351,7 @@
          * @param requiresCharging true if sync requires the phone to be plugged in. Default false.
          */
         public Builder setRequiresCharging(boolean requiresCharging) {
-            mRequiresCharging = true;
+            mRequiresCharging = requiresCharging;
             return this;
         }
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ab641c9..b20b5e2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1741,6 +1741,22 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API
+     * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate
+     * what level of optional compute features are supported beyond the Vulkan 1.0 requirements.
+     * <p>
+     * Compute level 0 indicates support for:
+     * <ul>
+     * <li>Ability to use pointers to buffer data from shaders</li>
+     * <li>Ability to load/store 16-bit values from buffers</li>
+     * <li>Ability to control shader floating point rounding mode</li>
+     * </ul>
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature(String, int)}: The version of this feature indicates the highest
      * {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices that support
      * the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The feature version
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 3cf36d7..bf81096 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -753,7 +753,7 @@
         }
 
         final String file = value.string.toString();
-        Typeface cached = Typeface.createFromCache(mAssets, file);
+        Typeface cached = Typeface.findFromCache(mAssets, file);
         if (cached != null) {
             return cached;
         }
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 522575f..d951294 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -259,10 +259,6 @@
             throw new IllegalArgumentException("Unknow surface source class type");
         }
 
-        if (surfaceSize.getWidth() == 0 || surfaceSize.getHeight() == 0) {
-            throw new IllegalArgumentException("Surface size needs to be non-zero");
-        }
-
         mSurfaceGroupId = SURFACE_GROUP_ID_NONE;
         mSurfaces = new ArrayList<Surface>();
         mRotation = ROTATION_0;
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 3eb5844..98a5749 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -230,9 +230,6 @@
         public int dozeScreenBrightness;
         public int dozeScreenState;
 
-        // If true, use twilight to affect the brightness.
-        public boolean useTwilight;
-
         public DisplayPowerRequest() {
             policy = POLICY_BRIGHT;
             useProximitySensor = false;
@@ -268,7 +265,6 @@
             boostScreenBrightness = other.boostScreenBrightness;
             dozeScreenBrightness = other.dozeScreenBrightness;
             dozeScreenState = other.dozeScreenState;
-            useTwilight = other.useTwilight;
         }
 
         @Override
@@ -289,8 +285,7 @@
                     && lowPowerMode == other.lowPowerMode
                     && boostScreenBrightness == other.boostScreenBrightness
                     && dozeScreenBrightness == other.dozeScreenBrightness
-                    && dozeScreenState == other.dozeScreenState
-                    && useTwilight == other.useTwilight;
+                    && dozeScreenState == other.dozeScreenState;
         }
 
         @Override
@@ -310,8 +305,7 @@
                     + ", lowPowerMode=" + lowPowerMode
                     + ", boostScreenBrightness=" + boostScreenBrightness
                     + ", dozeScreenBrightness=" + dozeScreenBrightness
-                    + ", dozeScreenState=" + Display.stateToString(dozeScreenState)
-                    + ", useTwilight=" + useTwilight;
+                    + ", dozeScreenState=" + Display.stateToString(dozeScreenState);
         }
 
         public static String policyToString(int policy) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 2c9e6c7..7947620 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -766,7 +766,7 @@
 
     /**
      * Retrieves the authenticator token for binding keys to the lifecycle
-     * of the current set of fingerprints. Used only by internal clients.
+     * of the calling user's fingerprints. Used only by internal clients.
      *
      * @hide
      */
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
index b89a245..9f97c5a 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -50,7 +50,7 @@
         private WifiConfiguration mDefaultConfig;
         private WifiConfiguration mConnectedConfig;
         private WifiConfiguration[] mConnectableConfigs;
-        private int mLastSelectedNetworkId;
+        private int mLastSelectedNetworkId = -1;
         private long mLastSelectedTimestamp;
 
         public Builder setScanResults(ScanResult[] scanResults) {
@@ -161,7 +161,7 @@
 
     /**
      * @return The {@link WifiConfiguration#networkId} of the last user selected network.
-     *         {@code 0} if not set.
+     *         {@code -1} if not set.
      */
     public int getLastSelectedNetworkId() {
         return mLastSelectedNetworkId;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index e99d303..f94e89a 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.IntegerRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -1339,7 +1340,7 @@
     }
 
     /**
-     * Flatten a heterogeneous array containing a particular object type into
+     * Flatten a homogeneous array containing a particular object type into
      * the parcel, at
      * the current dataPosition() and growing dataCapacity() if needed.  The
      * type of the objects in the array must be one that implements Parcelable.
@@ -1361,7 +1362,7 @@
         if (val != null) {
             int N = val.length;
             writeInt(N);
-            for (int i=0; i<N; i++) {
+            for (int i = 0; i < N; i++) {
                 T item = val[i];
                 if (item != null) {
                     writeInt(1);
@@ -1376,6 +1377,146 @@
     }
 
     /**
+     * Write a uniform (all items are null or the same class) array list of
+     * parcelables.
+     *
+     * @param list The list to write.
+     *
+     * @hide
+     */
+    public final <T extends Parcelable> void writeTypedArrayList(@Nullable ArrayList<T> list,
+            int parcelableFlags) {
+        if (list != null) {
+            int N = list.size();
+            writeInt(N);
+            boolean wroteCreator = false;
+            for (int i = 0; i < N; i++) {
+                T item = list.get(i);
+                if (item != null) {
+                    writeInt(1);
+                    if (!wroteCreator) {
+                        writeParcelableCreator(item);
+                        wroteCreator = true;
+                    }
+                    item.writeToParcel(this, parcelableFlags);
+                } else {
+                    writeInt(0);
+                }
+            }
+        } else {
+            writeInt(-1);
+        }
+    }
+
+    /**
+     * Reads a uniform (all items are null or the same class) array list of
+     * parcelables.
+     *
+     * @return The list or null.
+     *
+     * @hide
+     */
+    public final @Nullable <T> ArrayList<T> readTypedArrayList(@Nullable ClassLoader loader) {
+        int N = readInt();
+        if (N <= 0) {
+            return null;
+        }
+        Parcelable.Creator<?> creator = null;
+        ArrayList<T> result = new ArrayList<T>(N);
+        for (int i = 0; i < N; i++) {
+            if (readInt() != 0) {
+                if (creator == null) {
+                    creator = readParcelableCreator(loader);
+                    if (creator == null) {
+                        return null;
+                    }
+                }
+                final T parcelable;
+                if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+                    Parcelable.ClassLoaderCreator<?> classLoaderCreator =
+                            (Parcelable.ClassLoaderCreator<?>) creator;
+                    parcelable = (T) classLoaderCreator.createFromParcel(this, loader);
+                } else {
+                    parcelable = (T) creator.createFromParcel(this);
+                }
+                result.add(parcelable);
+            } else {
+                result.add(null);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Write a uniform (all items are null or the same class) array set of
+     * parcelables.
+     *
+     * @param set The set to write.
+     *
+     * @hide
+     */
+    public final <T extends Parcelable> void writeTypedArraySet(@Nullable ArraySet<T> set,
+            int parcelableFlags) {
+        if (set != null) {
+            int N = set.size();
+            writeInt(N);
+            boolean wroteCreator = false;
+            for (int i = 0; i < N; i++) {
+                T item = set.valueAt(i);
+                if (item != null) {
+                    writeInt(1);
+                    if (!wroteCreator) {
+                        writeParcelableCreator(item);
+                        wroteCreator = true;
+                    }
+                    item.writeToParcel(this, parcelableFlags);
+                } else {
+                    writeInt(0);
+                }
+            }
+        } else {
+            writeInt(-1);
+        }
+    }
+
+    /**
+     * Reads a uniform (all items are null or the same class) array set of
+     * parcelables.
+     *
+     * @return The set or null.
+     *
+     * @hide
+     */
+    public final @Nullable <T> ArraySet<T> readTypedArraySet(@Nullable ClassLoader loader) {
+        int N = readInt();
+        if (N <= 0) {
+            return null;
+        }
+        Parcelable.Creator<?> creator = null;
+        ArraySet<T> result = new ArraySet<T>(N);
+        for (int i = 0; i < N; i++) {
+            T parcelable = null;
+            if (readInt() != 0) {
+                if (creator == null) {
+                    creator = readParcelableCreator(loader);
+                    if (creator == null) {
+                        return null;
+                    }
+                }
+                if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
+                    Parcelable.ClassLoaderCreator<?> classLoaderCreator =
+                            (Parcelable.ClassLoaderCreator<?>) creator;
+                    parcelable = (T) classLoaderCreator.createFromParcel(this, loader);
+                } else {
+                    parcelable = (T) creator.createFromParcel(this);
+                }
+            }
+            result.append(parcelable);
+        }
+        return result;
+    }
+
+    /**
      * Flatten the Parcelable object into the parcel.
      *
      * @param val The Parcelable object to be written.
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index dff0a28..31b3bc9 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -508,15 +508,6 @@
     }
 
     /**
-     * Returns true if the twilight service should be used to adjust screen brightness
-     * policy.  This setting is experimental and disabled by default.
-     * @hide
-     */
-    public static boolean useTwilightAdjustmentFeature() {
-        return SystemProperties.getBoolean("persist.power.usetwilightadj", false);
-    }
-
-    /**
      * Creates a new wake lock with the specified level and flags.
      * <p>
      * The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 06666f4..5e7f68b 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.animation.LayoutTransition;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.XmlRes;
@@ -87,7 +88,7 @@
  * items.  Doing this implicitly switches the class into its new "headers
  * + fragments" mode rather than the old style of just showing a single
  * preferences list.
- * 
+ *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For information about using {@code PreferenceActivity},
@@ -199,6 +200,9 @@
 
     private ViewGroup mPrefsContainer;
 
+    // Null if in legacy mode.
+    private ViewGroup mHeadersContainer;
+
     private FragmentBreadCrumbs mFragmentBreadCrumbs;
 
     private boolean mSinglePane;
@@ -292,7 +296,7 @@
                 holder = (HeaderViewHolder) view.getTag();
             }
 
-            // All view fields must be updated every time, because the view may be recycled 
+            // All view fields must be updated every time, because the view may be recycled
             Header header = getItem(position);
             if (mRemoveIconIfEmpty) {
                 if (header.iconRes == 0) {
@@ -469,7 +473,7 @@
             }
             return breadCrumbShortTitle;
         }
-        
+
         @Override
         public int describeContents() {
             return 0;
@@ -558,6 +562,7 @@
 
         mListFooter = (FrameLayout)findViewById(com.android.internal.R.id.list_footer);
         mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs_frame);
+        mHeadersContainer = (ViewGroup) findViewById(com.android.internal.R.id.headers);
         boolean hidingHeaders = onIsHidingHeaders();
         mSinglePane = hidingHeaders || !onIsMultiPane();
         String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
@@ -575,66 +580,39 @@
                         (int) HEADER_ID_UNDEFINED);
                 if (curHeader >= 0 && curHeader < mHeaders.size()) {
                     setSelectedHeader(mHeaders.get(curHeader));
+                } else if (!mSinglePane && initialFragment == null) {
+                    switchToHeader(onGetInitialHeader());
                 }
+            } else {
+                // This will for instance hide breadcrumbs for single pane.
+                showBreadCrumbs(getTitle(), null);
+            }
+        } else {
+            if (!onIsHidingHeaders()) {
+                onBuildHeaders(mHeaders);
             }
 
-        } else {
-            if (initialFragment != null && mSinglePane) {
-                // If we are just showing a fragment, we want to run in
-                // new fragment mode, but don't need to compute and show
-                // the headers.
+            if (initialFragment != null) {
                 switchToHeader(initialFragment, initialArguments);
-                if (initialTitle != 0) {
-                    CharSequence initialTitleStr = getText(initialTitle);
-                    CharSequence initialShortTitleStr = initialShortTitle != 0
-                            ? getText(initialShortTitle) : null;
-                    showBreadCrumbs(initialTitleStr, initialShortTitleStr);
-                }
-
-            } else {
-                // We need to try to build the headers.
-                onBuildHeaders(mHeaders);
-
-                // If there are headers, then at this point we need to show
-                // them and, depending on the screen, we may also show in-line
-                // the currently selected preference fragment.
-                if (mHeaders.size() > 0) {
-                    if (!mSinglePane) {
-                        if (initialFragment == null) {
-                            Header h = onGetInitialHeader();
-                            switchToHeader(h);
-                        } else {
-                            switchToHeader(initialFragment, initialArguments);
-                        }
-                    }
-                }
+            } else if (!mSinglePane && mHeaders.size() > 0) {
+                switchToHeader(onGetInitialHeader());
             }
         }
 
-        // The default configuration is to only show the list view.  Adjust
-        // visibility for other configurations.
-        if (initialFragment != null && mSinglePane) {
-            // Single pane, showing just a prefs fragment.
-            findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
-            mPrefsContainer.setVisibility(View.VISIBLE);
-            if (initialTitle != 0) {
-                CharSequence initialTitleStr = getText(initialTitle);
-                CharSequence initialShortTitleStr = initialShortTitle != 0
-                        ? getText(initialShortTitle) : null;
-                showBreadCrumbs(initialTitleStr, initialShortTitleStr);
-            }
-        } else if (mHeaders.size() > 0) {
+        if (mHeaders.size() > 0) {
             setListAdapter(new HeaderAdapter(this, mHeaders, mPreferenceHeaderItemResId,
                     mPreferenceHeaderRemoveEmptyIcon));
-            if (!mSinglePane) {
-                // Multi-pane.
-                getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
-                if (mCurHeader != null) {
-                    setSelectedHeader(mCurHeader);
-                }
-                mPrefsContainer.setVisibility(View.VISIBLE);
-            }
-        } else {
+            getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+        }
+
+        if (mSinglePane && initialFragment != null && initialTitle != 0) {
+            CharSequence initialTitleStr = getText(initialTitle);
+            CharSequence initialShortTitleStr = initialShortTitle != 0
+                    ? getText(initialShortTitle) : null;
+            showBreadCrumbs(initialTitleStr, initialShortTitleStr);
+        }
+
+        if (mHeaders.size() == 0 && initialFragment == null) {
             // If there are no headers, we are in the old "just show a screen
             // of preferences" mode.
             setContentView(com.android.internal.R.layout.preference_list_content_single);
@@ -642,6 +620,25 @@
             mPrefsContainer = (ViewGroup) findViewById(com.android.internal.R.id.prefs);
             mPreferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE);
             mPreferenceManager.setOnPreferenceTreeClickListener(this);
+            mHeadersContainer = null;
+        } else if (mSinglePane) {
+            // Single-pane so one of the header or prefs containers must be hidden.
+            if (initialFragment != null || mCurHeader != null) {
+                mHeadersContainer.setVisibility(View.GONE);
+            } else {
+                mPrefsContainer.setVisibility(View.GONE);
+            }
+
+            // This animates our manual transitions between headers and prefs panel in single-pane.
+            // It also comes last so we don't animate any initial layout changes done above.
+            ViewGroup container = (ViewGroup) findViewById(
+                    com.android.internal.R.id.prefs_container);
+            container.setLayoutTransition(new LayoutTransition());
+        } else {
+            // Multi-pane
+            if (mHeaders.size() > 0 && mCurHeader != null) {
+                setSelectedHeader(mCurHeader);
+            }
         }
 
         // see if we should show Back/Next buttons
@@ -697,12 +694,25 @@
         }
     }
 
+    @Override
+    public void onBackPressed() {
+        if (mCurHeader != null && mSinglePane && getFragmentManager().getBackStackEntryCount() == 0
+                && getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT) == null) {
+            mCurHeader = null;
+
+            mPrefsContainer.setVisibility(View.GONE);
+            mHeadersContainer.setVisibility(View.VISIBLE);
+            getListView().clearChoices();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
     /**
      * Returns true if this activity is currently showing the header list.
      */
     public boolean hasHeaders() {
-        return getListView().getVisibility() == View.VISIBLE
-                && mPreferenceManager == null;
+        return mHeadersContainer != null && mHeadersContainer.getVisibility() == View.VISIBLE;
     }
 
     /**
@@ -718,7 +728,7 @@
      * and a preference fragment.
      */
     public boolean isMultiPane() {
-        return hasHeaders() && mPrefsContainer.getVisibility() == View.VISIBLE;
+        return !mSinglePane;
     }
 
     /**
@@ -820,14 +830,14 @@
             if (!"preference-headers".equals(nodeName)) {
                 throw new RuntimeException(
                         "XML document must start with <preference-headers> tag; found"
-                        + nodeName + " at " + parser.getPositionDescription());
+                                + nodeName + " at " + parser.getPositionDescription());
             }
 
             Bundle curBundle = null;
 
             final int outerDepth = parser.getDepth();
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                     continue;
                 }
@@ -889,7 +899,7 @@
 
                     final int innerDepth = parser.getDepth();
                     while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                           && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+                            && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
                         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                             continue;
                         }
@@ -939,8 +949,9 @@
         if (getApplicationInfo().targetSdkVersion  >= android.os.Build.VERSION_CODES.KITKAT) {
             throw new RuntimeException(
                     "Subclasses of PreferenceActivity must override isValidFragment(String)"
-                    + " to verify that the Fragment class is valid! " + this.getClass().getName()
-                    + " has not checked if fragment " + fragmentName + " is valid.");
+                            + " to verify that the Fragment class is valid! "
+                            + this.getClass().getName()
+                            + " has not checked if fragment " + fragmentName + " is valid.");
         } else {
             return true;
         }
@@ -1017,6 +1028,13 @@
         // Only call this if we didn't save the instance state for later.
         // If we did save it, it will be restored when we bind the adapter.
         super.onRestoreInstanceState(state);
+
+        if (!mSinglePane) {
+            // Multi-pane.
+            if (mCurHeader != null) {
+                setSelectedHeader(mCurHeader);
+            }
+        }
     }
 
     @Override
@@ -1061,18 +1079,7 @@
      */
     public void onHeaderClick(Header header, int position) {
         if (header.fragment != null) {
-            if (mSinglePane) {
-                int titleRes = header.breadCrumbTitleRes;
-                int shortTitleRes = header.breadCrumbShortTitleRes;
-                if (titleRes == 0) {
-                    titleRes = header.titleRes;
-                    shortTitleRes = 0;
-                }
-                startWithFragment(header.fragment, header.fragmentArguments, null, 0,
-                        titleRes, shortTitleRes);
-            } else {
-                switchToHeader(header);
-            }
+            switchToHeader(header);
         } else if (header.intent != null) {
             startActivity(header.intent);
         }
@@ -1084,7 +1091,7 @@
      * the selected fragment.  The default implementation constructs an Intent
      * that re-launches the current activity with the appropriate arguments to
      * display the fragment.
-     * 
+     *
      * @param fragmentName The name of the fragment to display.
      * @param args Optional arguments to supply to the fragment.
      * @param titleRes Optional resource ID of title to show for this item.
@@ -1103,7 +1110,7 @@
         intent.putExtra(EXTRA_NO_HEADERS, true);
         return intent;
     }
-    
+
     /**
      * Like {@link #startWithFragment(String, Bundle, Fragment, int, int, int)}
      * but uses a 0 titleRes.
@@ -1223,11 +1230,21 @@
             throw new IllegalArgumentException("Invalid fragment for this activity: "
                     + fragmentName);
         }
+
         Fragment f = Fragment.instantiate(this, fragmentName, args);
         FragmentTransaction transaction = getFragmentManager().beginTransaction();
-        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+        transaction.setTransition(mSinglePane
+                ? FragmentTransaction.TRANSIT_NONE
+                : FragmentTransaction.TRANSIT_FRAGMENT_FADE);
         transaction.replace(com.android.internal.R.id.prefs, f);
         transaction.commitAllowingStateLoss();
+
+        if (mSinglePane && mPrefsContainer.getVisibility() == View.GONE) {
+            // We are transitioning from headers to preferences panel in single-pane so we need
+            // to hide headers and show the prefs container.
+            mPrefsContainer.setVisibility(View.VISIBLE);
+            mHeadersContainer.setVisibility(View.GONE);
+        }
     }
 
     /**
@@ -1340,7 +1357,7 @@
      * be instantiated and placed in the appropriate pane.  If running in
      * single-pane mode, a new activity will be launched in which to show the
      * fragment.
-     * 
+     *
      * @param fragmentClass Full name of the class implementing the fragment.
      * @param args Any desired arguments to supply to the fragment.
      * @param titleRes Optional resource identifier of the title of this
@@ -1355,29 +1372,25 @@
      */
     public void startPreferencePanel(String fragmentClass, Bundle args, @StringRes int titleRes,
             CharSequence titleText, Fragment resultTo, int resultRequestCode) {
-        if (mSinglePane) {
-            startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
-        } else {
-            Fragment f = Fragment.instantiate(this, fragmentClass, args);
-            if (resultTo != null) {
-                f.setTargetFragment(resultTo, resultRequestCode);
-            }
-            FragmentTransaction transaction = getFragmentManager().beginTransaction();
-            transaction.replace(com.android.internal.R.id.prefs, f);
-            if (titleRes != 0) {
-                transaction.setBreadCrumbTitle(titleRes);
-            } else if (titleText != null) {
-                transaction.setBreadCrumbTitle(titleText);
-            }
-            transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
-            transaction.addToBackStack(BACK_STACK_PREFS);
-            transaction.commitAllowingStateLoss();
+        Fragment f = Fragment.instantiate(this, fragmentClass, args);
+        if (resultTo != null) {
+            f.setTargetFragment(resultTo, resultRequestCode);
         }
+        FragmentTransaction transaction = getFragmentManager().beginTransaction();
+        transaction.replace(com.android.internal.R.id.prefs, f);
+        if (titleRes != 0) {
+            transaction.setBreadCrumbTitle(titleRes);
+        } else if (titleText != null) {
+            transaction.setBreadCrumbTitle(titleText);
+        }
+        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+        transaction.addToBackStack(BACK_STACK_PREFS);
+        transaction.commitAllowingStateLoss();
     }
 
     /**
      * Called by a preference panel fragment to finish itself.
-     * 
+     *
      * @param caller The fragment that is asking to be finished.
      * @param resultCode Optional result code to send back to the original
      * launching fragment.
@@ -1385,21 +1398,16 @@
      * launching fragment.
      */
     public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
-        if (mSinglePane) {
-            setResult(resultCode, resultData);
-            finish();
-        } else {
-            // XXX be smarter about popping the stack.
-            onBackPressed();
-            if (caller != null) {
-                if (caller.getTargetFragment() != null) {
-                    caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
-                            resultCode, resultData);
-                }
+        // TODO: be smarter about popping the stack.
+        onBackPressed();
+        if (caller != null) {
+            if (caller.getTargetFragment() != null) {
+                caller.getTargetFragment().onActivityResult(caller.getTargetRequestCode(),
+                        resultCode, resultData);
             }
         }
     }
-    
+
     @Override
     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
         startPreferencePanel(pref.getFragment(), pref.getExtras(), pref.getTitleRes(),
diff --git a/core/java/android/provider/OneTimeUseBuilder.java b/core/java/android/provider/OneTimeUseBuilder.java
new file mode 100644
index 0000000..682e9c7
--- /dev/null
+++ b/core/java/android/provider/OneTimeUseBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.provider;
+
+/**
+ * A builder that facilitates prohibiting its use after an instance was created with it.
+ *
+ * Suggested usage:
+ * call {@link #checkNotUsed} in each setter, and {@link #markUsed} in {@link #build}
+ *
+ * @param <T> Type of object being built
+ * @hide
+ */
+public abstract class OneTimeUseBuilder<T> {
+    private boolean used = false;
+
+    protected void markUsed() {
+        checkNotUsed();
+        used = true;
+    }
+
+    protected void checkNotUsed() {
+        if (used) {
+            throw new IllegalStateException(
+                    "This Builder should not be reused. Use a new Builder instance instead");
+        }
+    }
+
+    /**
+     * Builds the instance
+     *
+     * Once this method is called, this builder should no longer be used. Any subsequent calls to a
+     * setter or {@code build()} will throw an exception
+     */
+    public abstract T build();
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d83f2cb..2936dfb 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6721,12 +6721,6 @@
         public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
 
         /**
-         * Whether brightness should automatically adjust based on twilight state.
-         * @hide
-         */
-        public static final String BRIGHTNESS_USE_TWILIGHT = "brightness_use_twilight";
-
-        /**
          * Names of the service components that the current user has explicitly allowed to
          * be a VR mode listener, separated by ':'.
          *
diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java
new file mode 100644
index 0000000..f242d79
--- /dev/null
+++ b/core/java/android/provider/SettingsStringUtil.java
@@ -0,0 +1,174 @@
+/*
+ * 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.provider;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.text.TextUtils;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.function.Function;
+
+/**
+ * Utilities for dealing with {@link String} values in {@link Settings}
+ *
+ * @hide
+ */
+public class SettingsStringUtil {
+    private SettingsStringUtil() {}
+
+    public static final String DELIMITER = ":";
+
+    /**
+     * A {@link HashSet} of items, that uses a common convention of setting string
+     * serialization/deserialization of separating multiple items with {@link #DELIMITER}
+     */
+    public static abstract class ColonDelimitedSet<T> extends HashSet<T> {
+
+        public ColonDelimitedSet(String colonSeparatedItems) {
+            for (String cn :
+                    TextUtils.split(TextUtils.emptyIfNull(colonSeparatedItems), DELIMITER)) {
+                add(itemFromString(cn));
+            }
+        }
+
+        protected abstract T itemFromString(String s);
+        protected String itemToString(T item) {
+            return String.valueOf(item);
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            Iterator<T> it = iterator();
+            if (it.hasNext()) {
+                sb.append(it.next());
+                while (it.hasNext()) {
+                    sb.append(DELIMITER);
+                    sb.append(itemToString(it.next()));
+                }
+            }
+            return sb.toString();
+        }
+
+
+        public static class OfStrings extends ColonDelimitedSet<String> {
+            public OfStrings(String colonSeparatedItems) {
+                super(colonSeparatedItems);
+            }
+
+            @Override
+            protected String itemFromString(String s) {
+                return s;
+            }
+
+            public static String add(String delimitedElements, String element) {
+                final ColonDelimitedSet<String> set
+                        = new ColonDelimitedSet.OfStrings(delimitedElements);
+                if (set.contains(element)) {
+                    return delimitedElements;
+                }
+                set.add(element);
+                return set.toString();
+            }
+
+            public static String remove(String delimitedElements, String element) {
+                final ColonDelimitedSet<String> set
+                        = new ColonDelimitedSet.OfStrings(delimitedElements);
+                if (!set.contains(element)) {
+                    return delimitedElements;
+                }
+                set.remove(element);
+                return set.toString();
+            }
+
+            public static boolean contains(String delimitedElements, String element) {
+                final String[] elements = TextUtils.split(delimitedElements, DELIMITER);
+                return ArrayUtils.indexOf(elements, element) != -1;
+            }
+        }
+    }
+
+    public static class ComponentNameSet extends ColonDelimitedSet<ComponentName> {
+        public ComponentNameSet(String colonSeparatedPackageNames) {
+            super(colonSeparatedPackageNames);
+        }
+
+        @Override
+        protected ComponentName itemFromString(String s) {
+            return ComponentName.unflattenFromString(s);
+        }
+
+        @Override
+        protected String itemToString(ComponentName item) {
+            return item.flattenToString();
+        }
+
+        public static String add(String delimitedElements, ComponentName element) {
+            final ComponentNameSet set = new ComponentNameSet(delimitedElements);
+            if (set.contains(element)) {
+                return delimitedElements;
+            }
+            set.add(element);
+            return set.toString();
+        }
+
+        public static String remove(String delimitedElements, ComponentName element) {
+            final ComponentNameSet set = new ComponentNameSet(delimitedElements);
+            if (!set.contains(element)) {
+                return delimitedElements;
+            }
+            set.remove(element);
+            return set.toString();
+        }
+
+        public static boolean contains(String delimitedElements, ComponentName element) {
+            return ColonDelimitedSet.OfStrings.contains(
+                    delimitedElements, element.flattenToString());
+        }
+    }
+
+    public static class SettingStringHelper {
+        private final ContentResolver mContentResolver;
+        private final String mSettingName;
+        private final int mUserId;
+
+        public SettingStringHelper(ContentResolver contentResolver, String name, int userId) {
+            mContentResolver = contentResolver;
+            mUserId = userId;
+            mSettingName = name;
+        }
+
+        public String read() {
+            return Settings.Secure.getStringForUser(
+                    mContentResolver, mSettingName, mUserId);
+        }
+
+        public boolean write(String value) {
+            return Settings.Secure.putStringForUser(
+                    mContentResolver, mSettingName, value, mUserId);
+        }
+
+        public boolean modify(Function<String, String> change) {
+            return write(change.apply(read()));
+        }
+    }
+}
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index bfaf23c..ab80aa3 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -15,7 +15,10 @@
  */
 package android.service.autofill;
 
-import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import com.android.internal.os.HandlerCaller;
 import android.annotation.SdkConstant;
 import android.app.Activity;
 import android.app.Service;
@@ -24,21 +27,13 @@
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
 import android.util.Log;
-import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 
-import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
 //TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
 //life-cycle (and how state could be maintained on server-side) is well documented.
 
@@ -48,12 +43,7 @@
  * <p>Apps providing auto-fill capabilities must extend this service.
  */
 public abstract class AutoFillService extends Service {
-
     private static final String TAG = "AutoFillService";
-    static final boolean DEBUG = true; // TODO(b/33197203): set to false once stable
-
-    // TODO(b/33197203): check for device's memory size instead of DEBUG?
-    static final boolean DEBUG_PENDING_CALLBACKS = DEBUG;
 
     /**
      * The {@link Intent} that must be declared as handled by the service.
@@ -77,87 +67,37 @@
      */
     public static final String SERVICE_META_DATA = "android.autofill";
 
-    // Internal bundle keys.
-    /** @hide */ public static final String KEY_CALLBACK = "callback";
-    /** @hide */ public static final String KEY_SAVABLE_IDS = "savable_ids";
-    /** @hide */ public static final String EXTRA_CRYPTO_OBJECT_ID = "crypto_object_id";
-
-    // 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, 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, 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";
-
-    /**
-     * Used to indicate the user selected an action that requires authentication.
-     */
-    public static final int FLAG_AUTHENTICATION_REQUESTED = 1 << 0;
-
-    /**
-     * Used to indicate the user authentication succeeded.
-     */
-    public static final int FLAG_AUTHENTICATION_SUCCESS = 1 << 1;
-
-    /**
-     * Used to indicate the user authentication failed.
-     */
-    public static final int FLAG_AUTHENTICATION_ERROR = 1 << 2;
-
-    /**
-     * Used when the service requested Fingerprint authentication but such option is not available.
-     */
-    public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE  = 1 << 3;
+    // Internal extras
+    /** @hide */
+    public static final String EXTRA_ACTIVITY_TOKEN =
+            "android.service.autofill.EXTRA_ACTIVITY_TOKEN";
 
     // Handler messages.
     private static final int MSG_CONNECT = 1;
     private static final int MSG_DISCONNECT = 2;
-    private static final int MSG_AUTO_FILL_ACTIVITY = 3;
-    private static final int MSG_AUTHENTICATE_FILL_RESPONSE = 4;
-    private static final int MSG_AUTHENTICATE_DATASET = 5;
-    private static final int MSG_SAVE = 6;
+    private static final int MSG_ON_FILL_REQUEST = 3;
+    private static final int MSG_ON_SAVE_REQUEST = 4;
 
     private final IAutoFillService mInterface = new IAutoFillService.Stub() {
-
         @Override
-        public void autoFill(AssistStructure structure, IAutoFillServerCallback callback) {
-            mHandlerCaller
-                    .obtainMessageOO(MSG_AUTO_FILL_ACTIVITY, structure, callback)
+        public void onFillRequest(AssistStructure structure, Bundle extras,
+                IFillCallback callback) {
+            ICancellationSignal transport = CancellationSignal.createTransport();
+            try {
+                callback.onCancellable(transport);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+            mHandlerCaller.obtainMessageOOOO(MSG_ON_FILL_REQUEST, structure,
+                    CancellationSignal.fromTransport(transport), extras, callback)
                     .sendToTarget();
         }
 
         @Override
-        public void save(AssistStructure structure, IAutoFillServerCallback callback,
-                Bundle extras) throws RemoteException {
-            mHandlerCaller
-                    .obtainMessageOOO(MSG_SAVE, structure, callback, extras)
-                    .sendToTarget();
-        }
-
-        @Override
-        public void authenticateFillResponse(Bundle extras, int flags) {
-            final Message msg = mHandlerCaller.obtainMessage(MSG_AUTHENTICATE_FILL_RESPONSE);
-            msg.arg1 = flags;
-            msg.obj = extras;
-            mHandlerCaller.sendMessage(msg);
-        }
-
-        @Override
-        public void authenticateDataset(Bundle extras, int flags) {
-            final Message msg = mHandlerCaller.obtainMessage(MSG_AUTHENTICATE_DATASET);
-            msg.arg1 = flags;
-            msg.obj = extras;
-            mHandlerCaller.sendMessage(msg);
+        public void onSaveRequest(AssistStructure structure, Bundle extras,
+                ISaveCallback callback) {
+            mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
+                    extras, callback).sendToTarget();
         }
 
         @Override
@@ -171,63 +111,41 @@
         }
     };
 
-    private final HandlerCaller.Callback mHandlerCallback = new HandlerCaller.Callback() {
-
-        @Override
-        public void executeMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_CONNECT: {
-                    onConnected();
-                    break;
-                } case MSG_AUTO_FILL_ACTIVITY: {
-                    final SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        final AssistStructure structure = (AssistStructure) args.arg1;
-                        final IAutoFillServerCallback callback =
-                                (IAutoFillServerCallback) args.arg2;
-                        handleAutoFill(structure, callback);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                } case MSG_SAVE: {
-                    final SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        final AssistStructure structure = (AssistStructure) args.arg1;
-                        final IAutoFillServerCallback callback =
-                                (IAutoFillServerCallback) args.arg2;
-                        final Bundle extras = (Bundle) args.arg3;
-                        handleSave(structure, callback, extras);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-                } case MSG_AUTHENTICATE_FILL_RESPONSE: {
-                    final int flags = msg.arg1;
-                    final Bundle extras = (Bundle) msg.obj;
-                    onFillResponseAuthenticationRequest(extras, flags);
-                    break;
-                } case MSG_AUTHENTICATE_DATASET: {
-                    final int flags = msg.arg1;
-                    final Bundle extras = (Bundle) msg.obj;
-                    onDatasetAuthenticationRequest(extras, flags);
-                    break;
-                } case MSG_DISCONNECT: {
-                    onDisconnected();
-                    break;
-                } default: {
-                    Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
-                }
+    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+        switch (msg.what) {
+            case MSG_CONNECT: {
+                onConnected();
+                break;
+            } case MSG_ON_FILL_REQUEST: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                final AssistStructure structure = (AssistStructure) args.arg1;
+                final CancellationSignal cancellation = (CancellationSignal) args.arg2;
+                final Bundle extras = (Bundle) args.arg3;
+                final IFillCallback callback = (IFillCallback) args.arg4;
+                final FillCallback fillCallback = new FillCallback(callback);
+                args.recycle();
+                onFillRequest(structure, extras, cancellation, fillCallback);
+                break;
+            } case MSG_ON_SAVE_REQUEST: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                final AssistStructure structure = (AssistStructure) args.arg1;
+                final Bundle extras = (Bundle) args.arg2;
+                final ISaveCallback callback = (ISaveCallback) args.arg3;
+                final SaveCallback saveCallback = new SaveCallback(callback);
+                args.recycle();
+                onSaveRequest(structure, extras, saveCallback);
+                break;
+            } case MSG_DISCONNECT: {
+                onDisconnected();
+                break;
+            } default: {
+                Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
             }
         }
     };
 
     private HandlerCaller mHandlerCaller;
 
-    // User for debugging purposes
-    private final List<CallbackHelper.Dumpable> mPendingCallbacks =
-            DEBUG_PENDING_CALLBACKS ? new ArrayList<>() : null;
-
     /**
      * {@inheritDoc}
      *
@@ -236,7 +154,6 @@
     @Override
     public void onCreate() {
         super.onCreate();
-
         mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
     }
 
@@ -255,7 +172,7 @@
      * <p>You should generally do initialization here rather than in {@link #onCreate}.
      */
     public void onConnected() {
-        if (DEBUG) Log.d(TAG, "onConnected()");
+
     }
 
     /**
@@ -267,14 +184,18 @@
      * 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 data bundle containing data passed by the service on previous calls to fill.
+     *     This bundle allows your service to keep state between fill and save requests
+     *     as well as when filling different sections of the UI as the system will try to
+     *     aggressively unbind from the service to conserve resources. See {@link FillResponse}
+     *     Javadoc for examples of multiple-sections requests.
+     * @param cancellationSignal signal for observing cancellation requests. The system will use
+     *     this to notify you that the fill result is no longer needed and you should stop
+     *     handling this fill request in order to save resources.
      * @param callback object used to notify the result of the request.
      */
-    public abstract void onFillRequest(AssistStructure structure, Bundle data,
-            CancellationSignal cancellationSignal, FillCallback callback);
+    public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
+            @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
 
     /**
      * Called when user requests service to save the fields of an {@link Activity}.
@@ -284,108 +205,15 @@
      * 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 in the {@link FillResponse} that originated this call.
+     * @param data bundle containing data passed by the service on previous calls to fill.
+     *     This bundle allows your service to keep state between fill and save requests
+     *     as well as when filling different sections of the UI as the system will try to
+     *     aggressively unbind from the service to conserve resources. See {@link FillResponse}
+     *     Javadoc for examples of multiple-sections requests.
      * @param callback object used to notify the result of the request.
      */
-    public abstract void onSaveRequest(AssistStructure structure, Bundle data,
-            SaveCallback callback);
-
-    /**
-     * Called as result of the user action for a {@link FillResponse} that required authentication.
-     *
-     * <p>When the {@link FillResponse} required authentication through
-     * {@link android.view.autofill.FillResponse.Builder#requiresCustomAuthentication(Bundle, int)},
-     * this call indicates the user is requesting the service to authenticate him/her (and
-     * {@code flags} contains {@link #FLAG_AUTHENTICATION_REQUESTED}), and {@code extras} contains
-     * the {@link Bundle} passed to that method.
-     *
-     * <p>When the {@link FillResponse} required authentication through
-     * {@link android.view.autofill.FillResponse.Builder#requiresFingerprintAuthentication(
-     * android.hardware.fingerprint.FingerprintManager.CryptoObject, Bundle, int)},
-     * {@code flags} this call contains the result of the fingerprint authentication (such as
-     * {@link #FLAG_AUTHENTICATION_SUCCESS}, {@link #FLAG_AUTHENTICATION_ERROR}, and
-     * {@link #FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}) and {@code extras} contains the
-     * {@link Bundle} passed to that method.
-     */
-    public void onFillResponseAuthenticationRequest(@SuppressWarnings("unused") Bundle extras,
-            int flags) {
-        if (DEBUG) Log.d(TAG, "onFillResponseAuthenticationRequest(): flags=" + flags);
-    }
-
-    /**
-     * Called as result of the user action for a {@link Dataset} that required authentication.
-     *
-     * <p>When the {@link Dataset} required authentication through
-     * {@link android.view.autofill.Dataset.Builder#requiresCustomAuthentication(Bundle, int)}, this
-     * call indicates the user is requesting the service to authenticate him/her (and {@code flags}
-     * contains {@link #FLAG_AUTHENTICATION_REQUESTED}), and {@code extras} contains the
-     * {@link Bundle} passed to that method.
-     *
-     * <p>When the {@link Dataset} required authentication through
-     * {@link android.view.autofill.Dataset.Builder#requiresFingerprintAuthentication(
-     * android.hardware.fingerprint.FingerprintManager.CryptoObject, Bundle, int)},
-     * {@code flags} this call contains the result of the fingerprint authentication (such as
-     * {@link #FLAG_AUTHENTICATION_SUCCESS}, {@link #FLAG_AUTHENTICATION_ERROR}, and
-     * {@link #FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}) and {@code extras} contains the
-     * {@link Bundle} passed to that method.
-     */
-    public void onDatasetAuthenticationRequest(@SuppressWarnings("unused") Bundle extras,
-            int flags) {
-        if (DEBUG) Log.d(TAG, "onDatasetAuthenticationRequest(): flags=" + flags);
-    }
-
-    @Override
-    @CallSuper
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mPendingCallbacks != null) {
-            pw.print("Number of pending callbacks: "); pw.println(mPendingCallbacks.size());
-            final String prefix = "  ";
-            for (int i = 0; i < mPendingCallbacks.size(); i++) {
-                final CallbackHelper.Dumpable cb = mPendingCallbacks.get(i);
-                pw.print('#'); pw.print(i + 1); pw.println(':');
-                cb.dump(prefix, pw);
-            }
-            pw.println();
-        } else {
-            pw.println("Dumping disabled");
-        }
-    }
-
-    private void handleAutoFill(AssistStructure structure, IAutoFillServerCallback callback) {
-        final FillCallback fillCallback = new FillCallback(callback);
-        if (DEBUG_PENDING_CALLBACKS) {
-            addPendingCallback(fillCallback);
-        }
-        // TODO(b/33197203): hook up the cancelationSignal
-        onFillRequest(structure, null, new CancellationSignal(), fillCallback);
-        return;
-    }
-
-    private void handleSave(AssistStructure structure, IAutoFillServerCallback callback,
-            Bundle extras) {
-        final SaveCallback saveCallback = new SaveCallback(callback);
-        if (DEBUG_PENDING_CALLBACKS) {
-            addPendingCallback(saveCallback);
-        }
-        onSaveRequest(structure, extras, saveCallback);
-    }
-
-    private void addPendingCallback(CallbackHelper.Dumpable callback) {
-        if (mPendingCallbacks == null) {
-            // Shouldn't happend since call is controlled by DEBUG_PENDING_CALLBACKS guard.
-            Log.wtf(TAG, "addPendingCallback(): mPendingCallbacks not set");
-            return;
-        }
-
-        if (DEBUG) Log.d(TAG, "Adding pending callback: " + callback);
-
-        callback.setFinalizer(() -> {
-            if (DEBUG) Log.d(TAG, "Removing pending callback: " + callback);
-            mPendingCallbacks.remove(callback);
-        });
-        mPendingCallbacks.add(callback);
-    }
+    public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
+            @NonNull SaveCallback callback);
 
     /**
      * Called when the Android system disconnects from the service.
@@ -393,6 +221,6 @@
      * <p> At this point this service may no longer be an active {@link AutoFillService}.
      */
     public void onDisconnected() {
-        if (DEBUG) Log.d(TAG, "onDisconnected()");
+
     }
 }
diff --git a/core/java/android/service/autofill/AutoFillServiceInfo.java b/core/java/android/service/autofill/AutoFillServiceInfo.java
index fd957f1..985e32f 100644
--- a/core/java/android/service/autofill/AutoFillServiceInfo.java
+++ b/core/java/android/service/autofill/AutoFillServiceInfo.java
@@ -16,6 +16,7 @@
 package android.service.autofill;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppGlobals;
 import android.content.ComponentName;
@@ -25,7 +26,6 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.os.RemoteException;
-import android.util.AndroidException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Xml;
@@ -40,13 +40,10 @@
 /**
  * {@link ServiceInfo} and meta-data about an {@link AutoFillService}.
  *
- * <p>Upon construction, if {@link #getParseError()} is {@code null}, then the service is configured
- * correctly. Otherwise, {@link #getParseError()} indicates the parsing error.
- *
  * @hide
  */
 public final class AutoFillServiceInfo {
-    static final String TAG = "AutoFillServiceInfo";
+    private static final String TAG = "AutoFillServiceInfo";
 
     private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
             throws PackageManager.NameNotFoundException {
@@ -63,10 +60,9 @@
         throw new PackageManager.NameNotFoundException(comp.toString());
     }
 
-    @Nullable
-    private final String mParseError;
-
+    @NonNull
     private final ServiceInfo mServiceInfo;
+
     @Nullable
     private final String mSettingsActivity;
 
@@ -77,17 +73,7 @@
 
     public AutoFillServiceInfo(PackageManager pm, ServiceInfo si) {
         mServiceInfo = si;
-        TypedArray metaDataArray;
-        try {
-            metaDataArray = getMetaDataArray(pm, si);
-        } catch (AndroidException e) {
-            mParseError = e.getMessage();
-            mSettingsActivity = null;
-            Log.w(TAG, mParseError, e);
-            return;
-        }
-
-        mParseError = null;
+        final TypedArray metaDataArray = getMetaDataArray(pm, si);
         if (metaDataArray != null) {
             mSettingsActivity =
                     metaDataArray.getString(R.styleable.AutoFillService_settingsActivity);
@@ -101,12 +87,11 @@
      * Gets the meta-data as a TypedArray, or null if not provided, or throws if invalid.
      */
     @Nullable
-    private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si)
-            throws AndroidException {
+    private static TypedArray getMetaDataArray(PackageManager pm, ServiceInfo si) {
         // Check for permissions.
         if (!Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
-            throw new AndroidException(
-                "Service does not require permission " + Manifest.permission.BIND_AUTO_FILL);
+            Log.e(TAG, "Service does not require permission " + Manifest.permission.BIND_AUTO_FILL);
+            return null;
         }
 
         // Get the AutoFill metadata, if declared.
@@ -125,11 +110,13 @@
                         && type != XmlPullParser.START_TAG) {
                 }
             } catch (XmlPullParserException | IOException e) {
-                throw new AndroidException("Error parsing auto fill service meta-data: " + e, e);
+                Log.e(TAG, "Error parsing auto fill service meta-data", e);
+                return null;
             }
 
             if (!"autofill-service".equals(parser.getName())) {
-                throw new AndroidException("Meta-data does not start with autofill-service tag");
+                Log.e(TAG, "Meta-data does not start with autofill-service tag");
+                return null;
             }
             attrs = Xml.asAttributeSet(parser);
 
@@ -138,7 +125,8 @@
             try {
                 res = pm.getResourcesForApplication(si.applicationInfo);
             } catch (PackageManager.NameNotFoundException e) {
-                throw new AndroidException("Error getting application resources: " + e, e);
+                Log.e(TAG, "Error getting application resources", e);
+                return null;
             }
 
             return res.obtainAttributes(attrs, R.styleable.AutoFillService);
@@ -147,11 +135,6 @@
         }
     }
 
-    @Nullable
-    public String getParseError() {
-        return mParseError;
-    }
-
     public ServiceInfo getServiceInfo() {
         return mServiceInfo;
     }
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 7cab7ae..a306809 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -16,56 +16,32 @@
 
 package android.service.autofill;
 
-import static android.service.autofill.AutoFillService.DEBUG;
-import static android.util.DebugUtils.flagsToString;
-
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.RemoteException;
-import android.service.autofill.CallbackHelper.Dumpable;
-import android.service.autofill.CallbackHelper.Finalizer;
-import android.util.Log;
-import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-
-import java.io.PrintWriter;
-
 /**
  * Handles auto-fill requests from the {@link AutoFillService} into the {@link Activity} being
  * auto-filled.
- *
- * <p>This class is thread safe.
  */
-public final class FillCallback implements Dumpable {
-
-    private static final String TAG = "FillCallback";
-
-    // NOTE: constants below are public so they can be used by flagsToString()
-    /** @hide */ public static final int STATE_INITIAL = 1 << 0;
-    /** @hide */ public static final int STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE = 1 << 1;
-    /** @hide */ public static final int STATE_WAITING_DATASET_AUTH_RESPONSE = 1 << 2;
-    /** @hide */ public static final int STATE_FINISHED_OK = 1 << 3;
-    /** @hide */ public static final int STATE_FINISHED_FAILURE = 1 << 4;
-    /** @hide */ public static final int STATE_FINISHED_ERROR = 1 << 5;
-    /** @hide */ public static final int STATE_FINISHED_AUTHENTICATED = 1 << 6;
-
-    private final IAutoFillServerCallback mCallback;
-
-    @GuardedBy("mCallback")
-    private int mState = STATE_INITIAL;
-
-    @GuardedBy("mCallback")
-    private Finalizer mFinalizer;
+public final class FillCallback implements Parcelable {
+    private final IFillCallback mCallback;
+    private boolean mCalled;
 
     /** @hide */
-    FillCallback(IAutoFillServerCallback callback) {
+    public FillCallback(IFillCallback callback) {
         mCallback = callback;
     }
 
+    /** @hide */
+    private FillCallback(Parcel parcel) {
+        mCallback = IFillCallback.Stub.asInterface(parcel.readStrongBinder());
+    }
+
     /**
      * Notifies the Android System that an
      * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
@@ -76,43 +52,12 @@
      * {@link FillResponse} for examples.
      */
     public void onSuccess(@Nullable FillResponse response) {
-        final boolean authRequired = response != null && response.isAuthRequired();
-
-        if (DEBUG) Log.d(TAG, "onSuccess(): authReq= " + authRequired + ", resp=" + response);
-
-        synchronized (mCallback) {
-            if (authRequired) {
-                assertOnStateLocked(STATE_INITIAL);
-            } else {
-                assertOnStateLocked(STATE_INITIAL | STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE
-                        | STATE_WAITING_DATASET_AUTH_RESPONSE);
-            }
-
-            try {
-                mCallback.showResponse(response);
-                if (authRequired) {
-                    mState = STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE;
-                } else {
-                    // Check if at least one dataset requires authentication.
-                    boolean waitingAuth = false;
-                    if (response != null) {
-                        for (Dataset dataset : response.getDatasets()) {
-                            if (dataset.isAuthRequired()) {
-                                waitingAuth = true;
-                                break;
-                            }
-                        }
-                    }
-                    if (waitingAuth) {
-                        mState = STATE_WAITING_DATASET_AUTH_RESPONSE;
-                    } else {
-                        setFinalStateLocked(STATE_FINISHED_OK);
-                    }
-                }
-            } catch (RemoteException e) {
-                setFinalStateLocked(STATE_FINISHED_ERROR);
-                e.rethrowAsRuntimeException();
-            }
+        assertNotCalled();
+        mCalled = true;
+        try {
+            mCallback.onSuccess(response);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -124,118 +69,43 @@
      *
      * @param message error message to be displayed to the user.
      */
-    public void onFailure(CharSequence message) {
-        if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
-
-        Preconditions.checkArgument(message != null, "message cannot be null");
-
-        synchronized (mCallback) {
-            assertOnStateLocked(STATE_INITIAL | STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE
-                    | STATE_WAITING_DATASET_AUTH_RESPONSE);
-
-            try {
-                mCallback.showError(message);
-                setFinalStateLocked(STATE_FINISHED_FAILURE);
-            } catch (RemoteException e) {
-                setFinalStateLocked(STATE_FINISHED_ERROR);
-                e.rethrowAsRuntimeException();
-            }
+    public void onFailure(@Nullable CharSequence message) {
+        assertNotCalled();
+        mCalled = true;
+        try {
+            mCallback.onFailure(message);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
-    /**
-     * Notifies the Android System when the user authenticated a {@link FillResponse} previously
-     * passed to {@link #onSuccess(FillResponse)}.
-     *
-     * @param flags must contain either
-     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} or
-     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}.
-     */
-    public void onFillResponseAuthentication(int flags) {
-        if (DEBUG) Log.d(TAG, "onFillResponseAuthentication(): flags=" + flags);
-
-        synchronized (mCallback) {
-            assertOnStateLocked(STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE);
-
-            try {
-                mCallback.unlockFillResponse(flags);
-                setFinalStateLocked(STATE_FINISHED_AUTHENTICATED);
-            } catch (RemoteException e) {
-                setFinalStateLocked(STATE_FINISHED_ERROR);
-                e.rethrowAsRuntimeException();
-            }
-        }
-    }
-
-    /**
-     * Notifies the Android System when the user authenticated a {@link Dataset} previously passed
-     * to {@link #onSuccess(FillResponse)}.
-     *
-     * @param dataset values to fill the activity with in case of successful authentication of a
-     * previously locked (and empty) dataset).
-     * @param flags must contain either
-     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} or
-     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}.
-     */
-    public void onDatasetAuthentication(@Nullable Dataset dataset, int flags) {
-        if (DEBUG) Log.d(TAG, "onDatasetAuthentication(): dataset=" + dataset + ", flags=" + flags);
-
-        synchronized (mCallback) {
-            assertOnStateLocked(STATE_WAITING_DATASET_AUTH_RESPONSE);
-
-            try {
-                mCallback.unlockDataset(dataset, flags);
-                setFinalStateLocked(STATE_FINISHED_AUTHENTICATED);
-            } catch (RemoteException e) {
-                setFinalStateLocked(STATE_FINISHED_ERROR);
-                e.rethrowAsRuntimeException();
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (!DEBUG) return super.toString();
-
-        return "FillCallback: [mState = " + mState + "]";
-    }
-
     /** @hide */
     @Override
-    public void dump(String prefix, PrintWriter pw) {
-        pw.print(prefix); pw.print("FillCallback: mState="); pw.println(mState);
+    public int describeContents() {
+        return 0;
     }
 
     /** @hide */
     @Override
-    public void setFinalizer(Finalizer f) {
-        synchronized (mCallback) {
-            mFinalizer = f;
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeStrongBinder(mCallback.asBinder());
+    }
+
+    private void assertNotCalled() {
+        if (mCalled) {
+            throw new IllegalStateException("Already called");
         }
     }
 
-    /**
-     * Sets a final state (where the callback cannot be used anymore) and notifies the
-     * {@link Finalizer} (if any).
-     */
-    private void setFinalStateLocked(int state) {
-        if (DEBUG) Log.d(TAG, "setFinalState(): " + state);
-        mState = state;
-
-        if (mFinalizer != null) {
-            mFinalizer.gone();
+    public static final Creator<FillCallback> CREATOR = new Creator<FillCallback>() {
+        @Override
+        public FillCallback createFromParcel(Parcel parcel) {
+            return new FillCallback(parcel);
         }
-    }
 
-    // TODO(b/33197203): move and/or re-add state check logic on server side to avoid malicious app
-    // calling the callback on wrong state.
-
-    // Make sure callback method is called during the proper lifecycle state.
-    private void assertOnStateLocked(int flags) {
-        if (DEBUG) Log.d(TAG, "assertOnState(): current=" + mState + ", required=" + flags);
-
-        Preconditions.checkState((flags & mState) != 0,
-                "invalid state: required " + flagsToString(FillCallback.class, "STATE_", flags)
-                + ", current is " + flagsToString(FillCallback.class, "STATE_", mState));
-    }
+        @Override
+        public FillCallback[] newArray(int size) {
+            return new FillCallback[size];
+        }
+    };
 }
diff --git a/core/java/android/service/autofill/IAutoFillAppCallback.aidl b/core/java/android/service/autofill/IAutoFillAppCallback.aidl
index 8c3898a..c2e72e8 100644
--- a/core/java/android/service/autofill/IAutoFillAppCallback.aidl
+++ b/core/java/android/service/autofill/IAutoFillAppCallback.aidl
@@ -18,6 +18,8 @@
 
 import java.util.List;
 
+import android.content.Intent;
+import android.content.IntentSender;
 import android.view.autofill.Dataset;
 
 /**
@@ -31,4 +33,15 @@
       * Auto-fills the activity with the contents of a dataset.
       */
     void autoFill(in Dataset dataset);
+
+    /**
+      * Start an intent sender from the context of the filled app
+      */
+    void startIntentSender(in IntentSender intent, in Intent fillInIntent);
+
+    /**
+      * Called by system_service to enable auto-fill in a session, after it was asynchronously
+      * started by the manager.
+      */
+    void enableSession();
 }
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
index 088e649..b39c0c8 100644
--- a/core/java/android/service/autofill/IAutoFillManagerService.aidl
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -18,6 +18,7 @@
 
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillValue;
 
@@ -27,16 +28,13 @@
  * {@hide}
  */
 oneway interface IAutoFillManagerService {
+    // Methods called by AutoFillManager
+    void startSession(in IBinder activityToken, in IBinder appCallback, in AutoFillId autoFillId,
+                      in Rect bounds, in AutoFillValue value);
+    void updateSession(in IBinder activityToken, in AutoFillId id, in Rect bounds,
+                       in AutoFillValue value, int flags);
+    void finishSession(in IBinder activityToken);
 
-    // Called by AutoFillManager (app).
-    void requestAutoFill(in AutoFillId id, in Rect bounds, int flags);
-
-    // Called by AutoFillManager (app).
-    void onValueChanged(in AutoFillId id, in AutoFillValue value);
-
-    // Called by ShellCommand only.
-    void requestAutoFillForUser(int userId);
-
-    // Called by ShellCommand only.
+    // Methods called by ShellCommand
     void requestSaveForUser(int userId);
 }
diff --git a/core/java/android/service/autofill/IAutoFillServerCallback.aidl b/core/java/android/service/autofill/IAutoFillServerCallback.aidl
deleted file mode 100644
index 480438a..0000000
--- a/core/java/android/service/autofill/IAutoFillServerCallback.aidl
+++ /dev/null
@@ -1,39 +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 java.util.List;
-
-import android.os.Bundle;
-import android.view.autofill.AutoFillId;
-import android.view.autofill.Dataset;
-import android.view.autofill.FillResponse;
-
-/**
- * Object running in the AutoFillService process and used to communicate back with system_server.
- *
- * @hide
- */
-// TODO(b/33197203): rename to IAutoFillServerSession
-oneway interface IAutoFillServerCallback {
-    // TODO(b/33197203): document methods
-    void showResponse(in FillResponse response);
-    void showError(CharSequence message);
-    void onSaved();
-    void unlockFillResponse(int flags);
-    void unlockDataset(in Dataset dataset, int flags);
-}
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index a4e6ebc..fa1ea65 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -18,19 +18,20 @@
 
 import android.app.assist.AssistStructure;
 import android.os.Bundle;
-import android.service.autofill.IAutoFillServerCallback;
+import android.service.autofill.IFillCallback;
+import android.service.autofill.ISaveCallback;
 import com.android.internal.os.IResultReceiver;
 
 /**
+ * Interface from the system to an auto fill service.
+ *
  * @hide
  */
-// TODO(b/33197203): document class and methods
 oneway interface IAutoFillService {
-    // TODO(b/33197203): rename method to make them more consistent
-    void autoFill(in AssistStructure structure, in IAutoFillServerCallback callback);
-    void save(in AssistStructure structure, in IAutoFillServerCallback callback, in Bundle extras);
-    void authenticateFillResponse(in Bundle extras, int flags);
-    void authenticateDataset(in Bundle extras, int flags);
+    void onFillRequest(in AssistStructure structure, in Bundle extras,
+            in IFillCallback callback);
+    void onSaveRequest(in AssistStructure structure, in Bundle extras,
+            in ISaveCallback callback);
     void onConnected();
     void onDisconnected();
 }
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/service/autofill/IFillCallback.aidl
similarity index 66%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/android/service/autofill/IFillCallback.aidl
index ded8f97..537403e 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -13,18 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.service.autofill;
 
-import java.io.PrintWriter;
+import android.os.ICancellationSignal;
 
-final class CallbackHelper {
+import android.view.autofill.FillResponse;
 
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
-
-    static interface Finalizer {
-        void gone();
-    }
+/**
+ * Interface to receive the result of a save request.
+ *
+ * @hide
+ */
+interface IFillCallback {
+    void onCancellable(in ICancellationSignal cancellation);
+    void onSuccess(in FillResponse response);
+    void onFailure(CharSequence message);
 }
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/android/service/autofill/ISaveCallback.aidl
similarity index 72%
rename from core/java/android/service/autofill/CallbackHelper.java
rename to core/java/android/service/autofill/ISaveCallback.aidl
index ded8f97..e260c73 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/android/service/autofill/ISaveCallback.aidl
@@ -13,18 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.service.autofill;
 
-import java.io.PrintWriter;
-
-final class CallbackHelper {
-
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
-
-    static interface Finalizer {
-        void gone();
-    }
+/**
+ * Interface to receive the result of a save request.
+ *
+ * @hide
+ */
+interface ISaveCallback {
+    void onSuccess();
+    void onFailure(CharSequence message);
 }
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index 9dd9795..46b3072 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -16,21 +16,9 @@
 
 package android.service.autofill;
 
-import static android.service.autofill.AutoFillService.DEBUG;
-
 import android.app.Activity;
-import android.app.assist.AssistStructure.ViewNode;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.service.autofill.CallbackHelper.Dumpable;
-import android.service.autofill.CallbackHelper.Finalizer;
-import android.util.Log;
-import android.view.autofill.AutoFillId;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
-
-import java.io.PrintWriter;
 
 /**
  * Handles save requests from the {@link AutoFillService} into the {@link Activity} being
@@ -38,20 +26,12 @@
  *
  * <p>This class is thread safe.
  */
-public final class SaveCallback implements Dumpable {
-
-    private static final String TAG = "SaveCallback";
-
-    private final IAutoFillServerCallback mCallback;
-
-    @GuardedBy("mCallback")
-    private boolean mReplied = false;
-
-    @GuardedBy("mCallback")
-    private Finalizer mFinalizer;
+public final class SaveCallback {
+    private final ISaveCallback mCallback;
+    private boolean mCalled;
 
     /** @hide */
-    SaveCallback(IAutoFillServerCallback callback) {
+    SaveCallback(ISaveCallback callback) {
         mCallback = callback;
     }
 
@@ -63,17 +43,12 @@
      * @throws RuntimeException if an error occurred while calling the Android System.
      */
     public void onSuccess() {
-        if (DEBUG) Log.d(TAG, "onSuccess()");
-
-        synchronized (mCallback) {
-            checkNotRepliedYetLocked();
-            try {
-                mCallback.onSaved();
-            } catch (RemoteException e) {
-                e.rethrowAsRuntimeException();
-            } finally {
-                setRepliedLocked();
-            }
+        assertNotCalled();
+        mCalled = true;
+        try {
+            mCallback.onSuccess();
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
@@ -87,54 +62,18 @@
      * @throws RuntimeException if an error occurred while calling the Android System.
      */
     public void onFailure(CharSequence message) {
-        if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
-
-        synchronized (mCallback) {
-            checkNotRepliedYetLocked();
-
-            try {
-                mCallback.showError(message);
-            } catch (RemoteException e) {
-                e.rethrowAsRuntimeException();
-            } finally {
-                setRepliedLocked();
-            }
+        assertNotCalled();
+        mCalled = true;
+        try {
+            mCallback.onFailure(message);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
         }
     }
 
-    /** @hide */
-    @Override
-    public void dump(String prefix, PrintWriter pw) {
-        pw.print(prefix); pw.print("SaveCallback: mReplied="); pw.println(mReplied);
-    }
-
-    /** @hide */
-    @Override
-    public void setFinalizer(Finalizer f) {
-        synchronized (mCallback) {
-            mFinalizer = f;
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (!DEBUG) return super.toString();
-
-        return "SaveCallback: [mReplied= " + mReplied + "]";
-    }
-
-    // There can be only one!!
-    private void checkNotRepliedYetLocked() {
-        Preconditions.checkState(!mReplied, "already replied");
-    }
-
-    private void setRepliedLocked() {
-        if (DEBUG) Log.d(TAG, "setReplied()");
-
-        mReplied = true;
-
-        if (mFinalizer != null) {
-            mFinalizer.gone();
+    private void assertNotCalled() {
+        if (mCalled) {
+            throw new IllegalStateException("Already called");
         }
     }
 }
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 887f4b6..1781c2a 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -130,6 +130,11 @@
      */
     public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
 
+    /**
+     * @hide
+     */
+    public static final String EXTRA_STATE = "state";
+
     private final H mHandler = new H(Looper.getMainLooper());
 
     private boolean mListening = false;
diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl
index 62ecab3..10e4177 100644
--- a/core/java/android/service/vr/IVrManager.aidl
+++ b/core/java/android/service/vr/IVrManager.aidl
@@ -42,5 +42,13 @@
      */
     boolean getVrModeState();
 
+    /**
+     * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
+     * remain in VR mode even if the foreground does not specify VR mode being enabled. Mainly used
+     * by VR viewers to indicate that a device is placed in a VR viewer.
+     *
+     * @param enabled true if the device should be placed in persistent VR mode.
+     */
+    void setPersistentVrModeEnabled(in boolean enabled);
 }
 
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index bb952ab..55aeb1e 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -62,6 +62,7 @@
 
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
 
 import java.lang.reflect.Array;
 import java.util.Iterator;
@@ -466,6 +467,16 @@
         return isEmpty(str) ? null : str;
     }
 
+    /** {@hide} */
+    public static String emptyIfNull(@Nullable String str) {
+        return str == null ? "" : str;
+    }
+
+    /** {@hide} */
+    public static String firstNotEmpty(@Nullable String a, @NonNull String b) {
+        return !isEmpty(a) ? a : Preconditions.checkStringNotEmpty(b);
+    }
+
     /**
      * Returns the length that the specified CharSequence would have if
      * spaces and ASCII control characters were trimmed from the start and end,
diff --git a/core/java/android/text/style/ClickableSpan.java b/core/java/android/text/style/ClickableSpan.java
index a183427..b098f16 100644
--- a/core/java/android/text/style/ClickableSpan.java
+++ b/core/java/android/text/style/ClickableSpan.java
@@ -22,7 +22,7 @@
 /**
  * If an object of this type is attached to the text of a TextView
  * with a movement method of LinkMovementMethod, the affected spans of
- * text can be selected.  If clicked, the {@link #onClick} method will
+ * text can be selected. If selected and clicked, the {@link #onClick} method will
  * be called.
  */
 public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index 4b0b065..5303855 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -141,9 +141,10 @@
      * child view will be relative to its parent's final position, so it may appear to "jump"
      * at the beginning.</p>
      *
-     * @return <code>true</code> when a changed parent should execute the transition
-     * inside the scene root's overlay or <code>false</code> if a parent change only
-     * affects the transform of the transitioning view.
+     * @param reparentWithOverlay <code>true</code> when a changed parent should execute the
+     *                            transition inside the scene root's overlay or <code>false</code>
+     *                            if a parent change only affects the transform of the transitioning
+     *                            view.
      * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
      */
     public void setReparentWithOverlay(boolean reparentWithOverlay) {
@@ -465,7 +466,7 @@
         }
     }
 
-    private static class GhostListener extends Transition.TransitionListenerAdapter {
+    private static class GhostListener extends TransitionListenerAdapter {
         private View mView;
         private View mStartView;
         private GhostView mGhostView;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 8823605..af2547e 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -2342,34 +2342,6 @@
     }
 
     /**
-     * Utility adapter class to avoid having to override all three methods
-     * whenever someone just wants to listen for a single event.
-     *
-     * @hide
-     * */
-    public static class TransitionListenerAdapter implements TransitionListener {
-        @Override
-        public void onTransitionStart(Transition transition) {
-        }
-
-        @Override
-        public void onTransitionEnd(Transition transition) {
-        }
-
-        @Override
-        public void onTransitionCancel(Transition transition) {
-        }
-
-        @Override
-        public void onTransitionPause(Transition transition) {
-        }
-
-        @Override
-        public void onTransitionResume(Transition transition) {
-        }
-    }
-
-    /**
      * Holds information about each animator used when a new transition starts
      * while other transitions are still running to determine whether a running
      * animation should be canceled or a new animation noop'd. The structure holds
diff --git a/core/java/android/transition/TransitionListenerAdapter.java b/core/java/android/transition/TransitionListenerAdapter.java
new file mode 100644
index 0000000..c217949
--- /dev/null
+++ b/core/java/android/transition/TransitionListenerAdapter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.transition;
+
+/**
+ * This adapter class provides empty implementations of the methods from {@link
+ * android.transition.Transition.TransitionListener}.
+ * Any custom listener that cares only about a subset of the methods of this listener can
+ * simply subclass this adapter class instead of implementing the interface directly.
+ */
+public abstract class TransitionListenerAdapter implements Transition.TransitionListener {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onTransitionStart(Transition transition) {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onTransitionEnd(Transition transition) {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onTransitionCancel(Transition transition) {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onTransitionPause(Transition transition) {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onTransitionResume(Transition transition) {
+    }
+}
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 6e4d78d..325ff38 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -298,7 +298,7 @@
                 previousRunningTransitions = new ArrayList<Transition>(currentTransitions);
             }
             currentTransitions.add(mTransition);
-            mTransition.addListener(new Transition.TransitionListenerAdapter() {
+            mTransition.addListener(new TransitionListenerAdapter() {
                 @Override
                 public void onTransitionEnd(Transition transition) {
                     ArrayList<Transition> currentTransitions =
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 13ee48e..4ff4840 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -17,9 +17,11 @@
 package android.view;
 
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN;
+import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
 
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.Binder;
 import android.os.Bundle;
@@ -29,7 +31,6 @@
 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;
@@ -93,6 +94,19 @@
         mPrefetcher = new AccessibilityNodePrefetcher();
     }
 
+    private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid) {
+        // If the interrogation is performed by the same thread as the main UI
+        // thread in this process, set the message as a static reference so
+        // after this call completes the same thread but in the interrogating
+        // client can handle the message to generate the result.
+        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
+            AccessibilityInteractionClient.getInstanceForThread(
+                    interrogatingTid).setSameThreadMessage(message);
+        } else {
+            mHandler.sendMessage(message);
+        }
+    }
+
     private boolean isShown(View view) {
         // The first two checks are made also made by isShown() which
         // however traverses the tree up to the parent to catch that.
@@ -106,7 +120,7 @@
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
             long accessibilityNodeId, Region interactiveRegion, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
-            long interrogatingTid, MagnificationSpec spec) {
+            long interrogatingTid, MagnificationSpec spec, Bundle arguments) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID;
         message.arg1 = flags;
@@ -118,18 +132,10 @@
         args.arg1 = callback;
         args.arg2 = spec;
         args.arg3 = interactiveRegion;
+        args.arg4 = arguments;
         message.obj = args;
 
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
+        scheduleMessage(message, interrogatingPid, interrogatingTid);
     }
 
     private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
@@ -143,6 +149,7 @@
             (IAccessibilityInteractionConnectionCallback) args.arg1;
         final MagnificationSpec spec = (MagnificationSpec) args.arg2;
         final Region interactiveRegion = (Region) args.arg3;
+        final Bundle arguments = (Bundle) args.arg4;
 
         args.recycle();
 
@@ -160,29 +167,12 @@
                 root = findViewByAccessibilityId(accessibilityViewId);
             }
             if (root != null && isShown(root)) {
-                mPrefetcher.prefetchAccessibilityNodeInfos(root, virtualDescendantId, flags, infos);
+                mPrefetcher.prefetchAccessibilityNodeInfos(
+                        root, virtualDescendantId, flags, infos, arguments);
             }
         } finally {
-            try {
-                mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-                applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
-                // Recycle if called from another process. Specs are cached in the
-                // system process and obtained from a pool when read from parcel.
-                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
-                    spec.recycle();
-                }
-                adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
-                callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
-                infos.clear();
-            } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-            }
-
-            // Recycle if called from the same process. Regions are obtained in
-            // the system process and instantiated  when read from parcel.
-            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
-                interactiveRegion.recycle();
-            }
+            updateInfosForViewportAndReturnFindNodeResult(
+                    infos, callback, interactionId, spec, interactiveRegion);
         }
     }
 
@@ -201,19 +191,9 @@
         args.arg2 = spec;
         args.arg3 = viewId;
         args.arg4 = interactiveRegion;
-
         message.obj = args;
 
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
+        scheduleMessage(message, interrogatingPid, interrogatingTid);
     }
 
     private void findAccessibilityNodeInfosByViewIdUiThread(Message message) {
@@ -227,7 +207,6 @@
         final MagnificationSpec spec = (MagnificationSpec) args.arg2;
         final String viewId = (String) args.arg3;
         final Region interactiveRegion = (Region) args.arg4;
-
         args.recycle();
 
         final List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
@@ -257,25 +236,8 @@
                 mAddNodeInfosForViewId.reset();
             }
         } finally {
-            try {
-                mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-                applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
-                // Recycle if called from another process. Specs are cached in the
-                // system process and obtained from a pool when read from parcel.
-                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
-                    spec.recycle();
-                }
-                adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
-                callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
-            } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-            }
-
-            // Recycle if called from the same process. Regions are obtained in
-            // the system process and instantiated  when read from parcel.
-            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
-                interactiveRegion.recycle();
-            }
+            updateInfosForViewportAndReturnFindNodeResult(
+                    infos, callback, interactionId, spec, interactiveRegion);
         }
     }
 
@@ -297,16 +259,7 @@
         args.arg4 = interactiveRegion;
         message.obj = args;
 
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
+        scheduleMessage(message, interrogatingPid, interrogatingTid);
     }
 
     private void findAccessibilityNodeInfosByTextUiThread(Message message) {
@@ -375,31 +328,14 @@
                 }
             }
         } finally {
-            try {
-                mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-                applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
-                // Recycle if called from another process. Specs are cached in the
-                // system process and obtained from a pool when read from parcel.
-                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
-                    spec.recycle();
-                }
-                adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
-                callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
-            } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-            }
-
-            // Recycle if called from the same process. Regions are obtained in
-            // the system process and instantiated  when read from parcel.
-            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
-                interactiveRegion.recycle();
-            }
+            updateInfosForViewportAndReturnFindNodeResult(
+                    infos, callback, interactionId, spec, interactiveRegion);
         }
     }
 
     public void findFocusClientThread(long accessibilityNodeId, int focusType,
             Region interactiveRegion, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FIND_FOCUS;
@@ -416,16 +352,7 @@
 
         message.obj = args;
 
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
+        scheduleMessage(message, interrogatingPid, interrogatingTid);
     }
 
     private void findFocusUiThread(Message message) {
@@ -497,31 +424,14 @@
                 }
             }
         } finally {
-            try {
-                mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-                applyAppScaleAndMagnificationSpecIfNeeded(focused, spec);
-                // Recycle if called from another process. Specs are cached in the
-                // system process and obtained from a pool when read from parcel.
-                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
-                    spec.recycle();
-                }
-                adjustIsVisibleToUserIfNeeded(focused, interactiveRegion);
-                callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
-            } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-            }
-
-            // Recycle if called from the same process. Regions are obtained in
-            // the system process and instantiated  when read from parcel.
-            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
-                interactiveRegion.recycle();
-            }
+            updateInfoForViewportAndReturnFindNodeResult(
+                    focused, callback, interactionId, spec, interactiveRegion);
         }
     }
 
     public void focusSearchClientThread(long accessibilityNodeId, int direction,
             Region interactiveRegion, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid, MagnificationSpec spec) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_FOCUS_SEARCH;
@@ -537,16 +447,7 @@
 
         message.obj = args;
 
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
+        scheduleMessage(message, interrogatingPid, interrogatingTid);
     }
 
     private void focusSearchUiThread(Message message) {
@@ -582,31 +483,14 @@
                 }
             }
         } finally {
-            try {
-                mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
-                applyAppScaleAndMagnificationSpecIfNeeded(next, spec);
-                // Recycle if called from another process. Specs are cached in the
-                // system process and obtained from a pool when read from parcel.
-                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
-                    spec.recycle();
-                }
-                adjustIsVisibleToUserIfNeeded(next, interactiveRegion);
-                callback.setFindAccessibilityNodeInfoResult(next, interactionId);
-            } catch (RemoteException re) {
-                /* ignore - the other side will time out */
-            }
-
-            // Recycle if called from the same process. Regions are obtained in
-            // the system process and instantiated  when read from parcel.
-            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
-                interactiveRegion.recycle();
-            }
+            updateInfoForViewportAndReturnFindNodeResult(
+                    next, callback, interactionId, spec, interactiveRegion);
         }
     }
 
     public void performAccessibilityActionClientThread(long accessibilityNodeId, int action,
             Bundle arguments, int interactionId,
-            IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
+            IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
             long interrogatingTid) {
         Message message = mHandler.obtainMessage();
         message.what = PrivateHandler.MSG_PERFORM_ACCESSIBILITY_ACTION;
@@ -622,16 +506,7 @@
 
         message.obj = args;
 
-        // If the interrogation is performed by the same thread as the main UI
-        // thread in this process, set the message as a static reference so
-        // after this call completes the same thread but in the interrogating
-        // client can handle the message to generate the result.
-        if (interogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
-            AccessibilityInteractionClient.getInstanceForThread(
-                    interrogatingTid).setSameThreadMessage(message);
-        } else {
-            mHandler.sendMessage(message);
-        }
+        scheduleMessage(message, interrogatingPid, interrogatingTid);
     }
 
     private void performAccessibilityActionUiThread(Message message) {
@@ -742,26 +617,6 @@
         }
     }
 
-    private void applyAppScaleAndMagnificationSpecIfNeeded(Point point,
-            MagnificationSpec spec) {
-        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
-        if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
-            return;
-        }
-
-        if (applicationScale != 1.0f) {
-            point.x *= applicationScale;
-            point.y *= applicationScale;
-        }
-
-        if (spec != null) {
-            point.x *= spec.scale;
-            point.y *= spec.scale;
-            point.x += (int) spec.offsetX;
-            point.y += (int) spec.offsetY;
-        }
-    }
-
     private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
             MagnificationSpec spec) {
         if (info == null) {
@@ -791,6 +646,25 @@
         info.setBoundsInParent(boundsInParent);
         info.setBoundsInScreen(boundsInScreen);
 
+        // Scale text locations if they are present
+        if (info.hasExtras()) {
+            Bundle extras = info.getExtras();
+            Parcelable[] textLocations =
+                    extras.getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY);
+            if (textLocations != null) {
+                for (int i = 0; i < textLocations.length; i++) {
+                    // Unchecked cast - an app that puts other objects in this bundle with this
+                    // key will crash.
+                    RectF textLocation = ((RectF) textLocations[i]);
+                    textLocation.scale(applicationScale);
+                    if (spec != null) {
+                        textLocation.scale(spec.scale);
+                        textLocation.offset(spec.offsetX, spec.offsetY);
+                    }
+                }
+            }
+        }
+
         if (spec != null) {
             AttachInfo attachInfo = mViewRootImpl.mAttachInfo;
             if (attachInfo.mDisplay == null) {
@@ -829,6 +703,53 @@
         return (appScale != 1.0f || (spec != null && !spec.isNop()));
     }
 
+    private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos,
+            IAccessibilityInteractionConnectionCallback callback, int interactionId,
+            MagnificationSpec spec, Region interactiveRegion) {
+        try {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+            applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
+            adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
+            callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
+            infos.clear();
+        } catch (RemoteException re) {
+            /* ignore - the other side will time out */
+        } finally {
+            recycleMagnificationSpecAndRegionIfNeeded(spec, interactiveRegion);
+        }
+    }
+
+    private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info,
+            IAccessibilityInteractionConnectionCallback callback, int interactionId,
+            MagnificationSpec spec, Region interactiveRegion) {
+        try {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+            applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
+            adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
+            callback.setFindAccessibilityNodeInfoResult(info, interactionId);
+        } catch (RemoteException re) {
+                /* ignore - the other side will time out */
+        } finally {
+            recycleMagnificationSpecAndRegionIfNeeded(spec, interactiveRegion);
+        }
+    }
+
+    private void recycleMagnificationSpecAndRegionIfNeeded(MagnificationSpec spec, Region region) {
+        if (android.os.Process.myPid() != Binder.getCallingPid()) {
+            // Specs are cached in the system process and obtained from a pool when read from
+            // a parcel, so only recycle the spec if called from another process.
+            if (spec != null) {
+                spec.recycle();
+            }
+        } else {
+            // Regions are obtained in the system process and instantiated when read from
+            // a parcel, so only recycle the region if caled from the same process.
+            if (region != null) {
+                region.recycle();
+            }
+        }
+    }
+
     private boolean handleClickableSpanActionUiThread(
             View view, int virtualDescendantId, Bundle arguments) {
         Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN);
@@ -872,11 +793,18 @@
         private final ArrayList<View> mTempViewList = new ArrayList<View>();
 
         public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int fetchFlags,
-                List<AccessibilityNodeInfo> outInfos) {
+                List<AccessibilityNodeInfo> outInfos, Bundle arguments) {
             AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+            // Determine if we'll be populating extra data
+            final String extraDataRequested = (arguments == null) ? null
+                    : arguments.getString(AccessibilityNodeInfo.EXTRA_DATA_REQUESTED_KEY);
             if (provider == null) {
                 AccessibilityNodeInfo root = view.createAccessibilityNodeInfo();
                 if (root != null) {
+                    if (extraDataRequested != null) {
+                        view.addExtraDataToAccessibilityNodeInfo(
+                                root, extraDataRequested, arguments);
+                    }
                     outInfos.add(root);
                     if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                         prefetchPredecessorsOfRealNode(view, outInfos);
@@ -889,14 +817,14 @@
                     }
                 }
             } else {
-                final AccessibilityNodeInfo root;
-                if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                    root = provider.createAccessibilityNodeInfo(virtualViewId);
-                } else {
-                    root = provider.createAccessibilityNodeInfo(
-                            AccessibilityNodeProvider.HOST_VIEW_ID);
-                }
+                final int idForRoot = (virtualViewId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
+                        ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualViewId;
+                final AccessibilityNodeInfo root = provider.createAccessibilityNodeInfo(idForRoot);
                 if (root != null) {
+                    if (extraDataRequested != null) {
+                        provider.addExtraDataToAccessibilityNodeInfo(
+                                idForRoot, root, extraDataRequested, arguments);
+                    }
                     outInfos.add(root);
                     if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                         prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos);
@@ -1202,12 +1130,12 @@
     }
 
     private class PrivateHandler extends Handler {
-        private final static int MSG_PERFORM_ACCESSIBILITY_ACTION = 1;
-        private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
-        private final static int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3;
-        private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4;
-        private final static int MSG_FIND_FOCUS = 5;
-        private final static int MSG_FOCUS_SEARCH = 6;
+        private static final int MSG_PERFORM_ACCESSIBILITY_ACTION = 1;
+        private static final int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
+        private static final int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3;
+        private static final int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4;
+        private static final int MSG_FIND_FOCUS = 5;
+        private static final int MSG_FOCUS_SEARCH = 6;
 
         public PrivateHandler(Looper looper) {
             super(looper);
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 41a13cf..7fde8a6 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -52,7 +52,9 @@
     final Rect mFocusedRect = new Rect();
     final Rect mOtherRect = new Rect();
     final Rect mBestCandidateRect = new Rect();
-    final SequentialFocusComparator mSequentialFocusComparator = new SequentialFocusComparator();
+    private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator =
+            new UserSpecifiedFocusComparator();
+    private final FocusComparator mFocusComparator = new FocusComparator();
 
     private final ArrayList<View> mTempList = new ArrayList<View>();
 
@@ -225,12 +227,10 @@
             View focused, Rect focusedRect, int direction) {
         try {
             // Note: This sort is stable.
-            mSequentialFocusComparator.setRoot(root);
-            mSequentialFocusComparator.setIsLayoutRtl(root.isLayoutRtl());
-            mSequentialFocusComparator.setFocusables(focusables);
-            Collections.sort(focusables, mSequentialFocusComparator);
+            mUserSpecifiedFocusComparator.setFocusables(focusables);
+            Collections.sort(focusables, mUserSpecifiedFocusComparator);
         } finally {
-            mSequentialFocusComparator.recycle();
+            mUserSpecifiedFocusComparator.recycle();
         }
 
         final int count = focusables.size();
@@ -703,36 +703,80 @@
         return id != 0 && id != View.NO_ID;
     }
 
-    /**
-     * Sorts views according to their visual layout and geometry for default tab order.
-     * If views are part of a focus chain (nextFocusForwardId), then they are all grouped
-     * together. The head of the chain is used to determine the order of the chain and is
-     * first in the order and the tail of the chain is the last in the order. The views
-     * in the middle of the chain can be arbitrary order.
-     * This is used for sequential focus traversal.
-     */
-    private static final class SequentialFocusComparator implements Comparator<View> {
+    static FocusComparator getFocusComparator(ViewGroup root, boolean isRtl) {
+        FocusComparator comparator = getInstance().mFocusComparator;
+        comparator.setRoot(root);
+        comparator.setIsLayoutRtl(isRtl);
+        return comparator;
+    }
+
+    static final class FocusComparator implements Comparator<View> {
         private final Rect mFirstRect = new Rect();
         private final Rect mSecondRect = new Rect();
-        private ViewGroup mRoot;
+        private ViewGroup mRoot = null;
         private boolean mIsLayoutRtl;
-        private final SparseArray<View> mFocusables = new SparseArray<View>();
-        private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
-        private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
 
-        public void recycle() {
-            mRoot = null;
-            mFocusables.clear();
-            mHeadsOfChains.clear();
-            mIsConnectedTo.clear();
+        public void setIsLayoutRtl(boolean b) {
+            mIsLayoutRtl = b;
         }
 
         public void setRoot(ViewGroup root) {
             mRoot = root;
         }
 
-        public void setIsLayoutRtl(boolean b) {
-            mIsLayoutRtl = b;
+        public int compare(View first, View second) {
+            if (first == second) {
+                return 0;
+            }
+
+            getRect(first, mFirstRect);
+            getRect(second, mSecondRect);
+
+            if (mFirstRect.top < mSecondRect.top) {
+                return -1;
+            } else if (mFirstRect.top > mSecondRect.top) {
+                return 1;
+            } else if (mFirstRect.left < mSecondRect.left) {
+                return mIsLayoutRtl ? 1 : -1;
+            } else if (mFirstRect.left > mSecondRect.left) {
+                return mIsLayoutRtl ? -1 : 1;
+            } else if (mFirstRect.bottom < mSecondRect.bottom) {
+                return -1;
+            } else if (mFirstRect.bottom > mSecondRect.bottom) {
+                return 1;
+            } else if (mFirstRect.right < mSecondRect.right) {
+                return mIsLayoutRtl ? 1 : -1;
+            } else if (mFirstRect.right > mSecondRect.right) {
+                return mIsLayoutRtl ? -1 : 1;
+            } else {
+                // The view are distinct but completely coincident so we consider
+                // them equal for our purposes.  Since the sort is stable, this
+                // means that the views will retain their layout order relative to one another.
+                return 0;
+            }
+        }
+
+        private void getRect(View view, Rect rect) {
+            view.getDrawingRect(rect);
+            mRoot.offsetDescendantRectToMyCoords(view, rect);
+        }
+    }
+
+    /**
+     * Sorts views according to any explicitly-specified focus-chains. If there are no explicitly
+     * specified focus chains (eg. no nextFocusForward attributes defined), this should be a no-op.
+     */
+    private static final class UserSpecifiedFocusComparator implements Comparator<View> {
+        private final SparseArray<View> mFocusables = new SparseArray<View>();
+        private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
+        private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
+        private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
+
+        public void recycle() {
+            mFocusables.clear();
+            mHeadsOfChains.clear();
+            mIsConnectedTo.clear();
+            mOriginalOrdinal.clear();
         }
 
         public void setFocusables(ArrayList<View> focusables) {
@@ -755,6 +799,10 @@
                     setHeadOfChain(view);
                 }
             }
+
+            for (int i = 0; i < focusables.size(); ++i) {
+                mOriginalOrdinal.put(focusables.get(i), i);
+            }
         }
 
         private void setHeadOfChain(View head) {
@@ -793,44 +841,22 @@
                     return 1; // first is end of chain
                 }
             }
+            boolean involvesChain = false;
             if (firstHead != null) {
                 first = firstHead;
+                involvesChain = true;
             }
             if (secondHead != null) {
                 second = secondHead;
+                involvesChain = true;
             }
 
-            // First see if they belong to the same focus chain.
-            getRect(first, mFirstRect);
-            getRect(second, mSecondRect);
-
-            if (mFirstRect.top < mSecondRect.top) {
-                return -1;
-            } else if (mFirstRect.top > mSecondRect.top) {
-                return 1;
-            } else if (mFirstRect.left < mSecondRect.left) {
-                return mIsLayoutRtl ? 1 : -1;
-            } else if (mFirstRect.left > mSecondRect.left) {
-                return mIsLayoutRtl ? -1 : 1;
-            } else if (mFirstRect.bottom < mSecondRect.bottom) {
-                return -1;
-            } else if (mFirstRect.bottom > mSecondRect.bottom) {
-                return 1;
-            } else if (mFirstRect.right < mSecondRect.right) {
-                return mIsLayoutRtl ? 1 : -1;
-            } else if (mFirstRect.right > mSecondRect.right) {
-                return mIsLayoutRtl ? -1 : 1;
+            if (involvesChain) {
+                // keep original order between chains
+                return mOriginalOrdinal.get(first) < mOriginalOrdinal.get(second) ? -1 : 1;
             } else {
-                // The view are distinct but completely coincident so we consider
-                // them equal for our purposes.  Since the sort is stable, this
-                // means that the views will retain their layout order relative to one another.
                 return 0;
             }
         }
-
-        private void getRect(View view, Rect rect) {
-            view.getDrawingRect(rect);
-            mRoot.offsetDescendantRectToMyCoords(view, rect);
-        }
     }
 }
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index d59be02..2fe98c0 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -16,8 +16,6 @@
 
 package android.view;
 
-import android.graphics.Rect;
-
 /**
  * An interface to the PinnedStackController to update it of state changes, and to query
  * information based on the current state.
@@ -27,17 +25,7 @@
 interface IPinnedStackController {
 
     /**
-     * Notifies the controller that the user is currently interacting with the PIP.
-     */
-    oneway void setInInteractiveMode(boolean inInteractiveMode);
-
-    /**
-     * Notifies the controller that the PIP is currently minimized.
+     * Notifies the controller that the PiP is currently minimized.
      */
     oneway void setIsMinimized(boolean isMinimized);
-
-    /**
-     * Notifies the controller that the desired snap mode is to the closest edge.
-     */
-    oneway void setSnapToEdge(boolean snapToEdge);
 }
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl
index 3c348c5..c7340bf 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.content.pm.ParceledListSlice;
+import android.graphics.Rect;
 import android.view.IPinnedStackController;
 
 /**
@@ -33,10 +34,22 @@
     void onListenerRegistered(IPinnedStackController controller);
 
     /**
-     * Called when window manager decides to adjust the pinned stack bounds, or when the listener
-     * is first registered to allow the listener to synchronized its state with the controller.
+     * Called when the window manager has detected a change that would cause the movement bounds
+     * to be changed (ie. after configuration change, aspect ratio change, etc). It then provides
+     * the components that allow the listener to calculate the movement bounds itself. The
+     * {@param normalBounds} are also the default bounds that the PiP would be entered in its
+     * current state with the aspect ratio applied.
      */
-    void onBoundsChanged(boolean adjustedForIme);
+    void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds,
+            boolean fromImeAdjustement);
+
+    /**
+     * Called when window manager decides to adjust the pinned stack bounds because of the IME, or
+     * when the listener is first registered to allow the listener to synchronized its state with
+     * the controller.  This call will always be followed by a onMovementBoundsChanged() call
+     * with fromImeAdjustement set to true.
+     */
+    void onImeVisibilityChanged(boolean imeVisible, int imeHeight);
 
     /**
      * Called when window manager decides to adjust the minimized state, or when the listener
@@ -45,14 +58,6 @@
     void onMinimizedStateChanged(boolean isMinimized);
 
     /**
-     * Called when window manager decides to adjust the snap-to-edge state, which determines whether
-     * to snap only to the corners of the screen or to the closest edge.  It is called when the
-     * listener is first registered to allow the listener to synchronized its state with the
-     * controller.
-     */
-    void onSnapToEdgeStateChanged(boolean isSnapToEdge);
-
-    /**
      * Called when the set of actions for the current PiP activity changes, or when the listener
      * is first registered to allow the listener to synchronized its state with the controller.
      */
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c789f8c..dd76fcf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -337,16 +337,6 @@
     void registerPinnedStackListener(int displayId, IPinnedStackListener listener);
 
     /**
-     * Returns the initial bounds that PIP will be shown when it is first started.
-     */
-    Rect getPictureInPictureDefaultBounds(int displayId);
-
-    /**
-     * Returns the bounds that the PIP can move on the screen in the current PIP state.
-     */
-    Rect getPictureInPictureMovementBounds(int displayId);
-
-    /**
      * Updates the dim layer used while resizing.
      *
      * @param visible Whether the dim layer should be visible.
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 0da710a..c3d3f39 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import android.annotation.Nullable;
+import android.app.Notification;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Outline;
@@ -39,7 +40,7 @@
  */
 @RemoteViews.RemoteView
 public class NotificationHeaderView extends ViewGroup {
-    public static final int NO_COLOR = -1;
+    public static final int NO_COLOR = Notification.COLOR_INVALID;
     private final int mChildMinWidth;
     private final int mContentEndMargin;
     private View mAppName;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e2eee95..ee97984 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6424,9 +6424,7 @@
         if (isAutoFillable()) {
             AutoFillManager afm = getAutoFillManager();
             if (afm != null) {
-                afm.updateAutoFillInput(this, gainFocus
-                        ? AutoFillManager.FLAG_UPDATE_UI_SHOW
-                        : AutoFillManager.FLAG_UPDATE_UI_HIDE);
+                afm.focusChanged(this, gainFocus);
             }
         }
 
@@ -6916,10 +6914,16 @@
         }
 
         if (forAutoFill) {
-            // 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());
+            final AutoFillType autoFillType = getAutoFillType();
+            // Don't need to fill auto-fill info if view does not support it.
+            // For example, only TextViews that are editable support auto-fill
+            if (autoFillType != null) {
+                // 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(autoFillType);
+                structure.setAutoFillValue(getAutoFillValue());
+            }
         }
 
         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
@@ -7015,16 +7019,15 @@
      * hierachy on {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}.
      */
     @Nullable
-    public VirtualViewDelegate getAutoFillVirtualViewDelegate(
-            @SuppressWarnings("unused") VirtualViewDelegate.Callback callback) {
+    public VirtualViewDelegate getAutoFillVirtualViewDelegate() {
         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>By default does nothing, but views should override it (and {@link #getAutoFillType()
+     * and #getAutoFillValue()} to support the AutoFill Framework.
      *
      * <p>Typically, it is implemented by:
      *
@@ -7058,6 +7061,18 @@
         return null;
     }
 
+    /**
+     * Gets the {@link View}'s current auto-fill value.
+     *
+     * <p>By default returns {@code null}, but views should override it,
+     * {@link #autoFill(AutoFillValue)}, and {@link #getAutoFillType()} to support the AutoFill
+     * Framework.
+     */
+    @Nullable
+    public AutoFillValue getAutoFillValue() {
+        return null;
+    }
+
     @Nullable
     private AutoFillManager getAutoFillManager() {
         return mContext.getSystemService(AutoFillManager.class);
@@ -7318,6 +7333,25 @@
     }
 
     /**
+     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
+     * additional data.
+     * <p>
+     * This method only needs overloading if the node is marked as having extra data available.
+     * </p>
+     *
+     * @param info The info to which to add the extra data
+     * @param extraDataKey A key specifying the type of extra data to add to the info. The
+     *                     extra data should be added to the {@link Bundle} returned by
+     *                     the info's {@link AccessibilityNodeInfo#getExtras} method.
+     * @param arguments A {@link Bundle} holding any arguments relevant for this request.
+     *
+     * @see AccessibilityNodeInfo#setExtraAvailableData
+     */
+    public void addExtraDataToAccessibilityNodeInfo(
+            AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
+    }
+
+    /**
      * Determine the order in which this view will be drawn relative to its siblings for a11y
      *
      * @param info The info whose drawing order should be populated
@@ -19942,9 +19976,9 @@
      * @return the view of the specified id, null if cannot be found
      * @hide
      */
-    protected <T extends View> T findViewTraversal(@IdRes int id) {
+    protected View findViewTraversal(@IdRes int id) {
         if (id == mID) {
-            return (T) this;
+            return this;
         }
         return null;
     }
@@ -19954,9 +19988,9 @@
      * @return the view of specified tag, null if cannot be found
      * @hide
      */
-    protected <T extends View> T findViewWithTagTraversal(Object tag) {
+    protected View findViewWithTagTraversal(Object tag) {
         if (tag != null && tag.equals(mTag)) {
-            return (T) this;
+            return this;
         }
         return null;
     }
@@ -19967,10 +20001,9 @@
      * @return The first view that matches the predicate or null.
      * @hide
      */
-    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
-            View childToSkip) {
+    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
         if (predicate.apply(this)) {
-            return (T) this;
+            return this;
         }
         return null;
     }
@@ -19983,7 +20016,7 @@
      * @return The view that has the given id in the hierarchy or null
      */
     @Nullable
-    public final <T extends View> T findViewById(@IdRes int id) {
+    public final View findViewById(@IdRes int id) {
         if (id < 0) {
             return null;
         }
@@ -19996,11 +20029,11 @@
      * @param accessibilityId The searched accessibility id.
      * @return The found view.
      */
-    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
+    final View findViewByAccessibilityId(int accessibilityId) {
         if (accessibilityId < 0) {
             return null;
         }
-        T view = findViewByAccessibilityIdTraversal(accessibilityId);
+        View view = findViewByAccessibilityIdTraversal(accessibilityId);
         if (view != null) {
             return view.includeForAccessibility() ? view : null;
         }
@@ -20019,11 +20052,12 @@
      *
      * @param accessibilityId The accessibility id.
      * @return The found view.
+     *
      * @hide
      */
-    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
+    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
         if (getAccessibilityViewId() == accessibilityId) {
-            return (T) this;
+            return this;
         }
         return null;
     }
@@ -20035,7 +20069,7 @@
      * @param tag The tag to search for, using "tag.equals(getTag())".
      * @return The View that has the given tag in the hierarchy or null
      */
-    public final <T extends View> T findViewWithTag(Object tag) {
+    public final View findViewWithTag(Object tag) {
         if (tag == null) {
             return null;
         }
@@ -20050,7 +20084,7 @@
      * @return The first view that matches the predicate or null.
      * @hide
      */
-    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
+    public final View findViewByPredicate(Predicate<View> predicate) {
         return findViewByPredicateTraversal(predicate, null);
     }
 
@@ -20070,11 +20104,10 @@
      * @return The first view that matches the predicate or null.
      * @hide
      */
-    public final <T extends View> T findViewByPredicateInsideOut(
-            View start, Predicate<View> predicate) {
+    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
         View childToSkip = null;
         for (;;) {
-            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
+            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
             if (view != null || start == this) {
                 return view;
             }
@@ -24320,6 +24353,32 @@
         }
 
         /**
+         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
+         * additional data.
+         * <p>
+         * This method only needs to be implemented if the View offers to provide additional data.
+         * </p>
+         * <p>
+         * The default implementation behaves as
+         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
+         * the case where no accessibility delegate is set.
+         * </p>
+         *
+         * @param host The View hosting the delegate.
+         * @param info The info to which to add the extra data
+         * @param extraDataKey A key specifying the type of extra data to add to the info. The
+         *                     extra data should be added to the {@link Bundle} returned by
+         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.
+         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
+         *
+         * @see AccessibilityNodeInfo#setExtraAvailableData
+         */
+        public void addExtraDataToAccessibilityNodeInfo(
+                View host, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
+            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
+        }
+
+        /**
          * Called when a child of the host View has requested sending an
          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
          * to augment the event.
@@ -24660,7 +24719,7 @@
      * Determine if this view is rendered on a round wearable device and is the main view
      * on the screen.
      */
-    private boolean shouldDrawRoundScrollbar() {
+    boolean shouldDrawRoundScrollbar() {
         if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
             return false;
         }
@@ -24677,7 +24736,7 @@
             return false;
         }
 
-        getLocationOnScreen(mAttachInfo.mTmpLocation);
+        getLocationInWindow(mAttachInfo.mTmpLocation);
         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index b11b3d7..36beaaa 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -60,6 +60,7 @@
 import com.android.internal.util.Predicate;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -1140,31 +1141,42 @@
         final int focusableCount = views.size();
 
         final int descendantFocusability = getDescendantFocusability();
+        final boolean focusSelf = (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen());
 
-        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
-            if (shouldBlockFocusForTouchscreen()) {
-                focusableMode |= FOCUSABLES_TOUCH_MODE;
+        if (descendantFocusability == FOCUS_BLOCK_DESCENDANTS) {
+            if (focusSelf) {
+                super.addFocusables(views, direction, focusableMode);
             }
-
-            final int count = mChildrenCount;
-            final View[] children = mChildren;
-
-            for (int i = 0; i < count; i++) {
-                final View child = children[i];
-                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
-                    child.addFocusables(views, direction, focusableMode);
-                }
-            }
+            return;
         }
 
-        // we add ourselves (if focusable) in all cases except for when we are
-        // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable.  this is
+        if (shouldBlockFocusForTouchscreen()) {
+            focusableMode |= FOCUSABLES_TOUCH_MODE;
+        }
+
+        if ((descendantFocusability == FOCUS_BEFORE_DESCENDANTS) && focusSelf) {
+            super.addFocusables(views, direction, focusableMode);
+        }
+
+        int count = 0;
+        final View[] children = new View[mChildrenCount];
+        for (int i = 0; i < mChildrenCount; ++i) {
+            View child = mChildren[i];
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+                children[count++] = child;
+            }
+        }
+        Arrays.sort(children, 0, count, FocusFinder.getFocusComparator(this, false));
+        for (int i = 0; i < count; ++i) {
+            children[i].addFocusables(views, direction, focusableMode);
+        }
+
+        // When set to FOCUS_AFTER_DESCENDANTS, we only add ourselves if
+        // there aren't any focusable descendants.  this is
         // to avoid the focus search finding layouts when a more precise search
         // among the focusable children would be more interesting.
-        if ((descendantFocusability != FOCUS_AFTER_DESCENDANTS
-                // No focusable descendants
-                || (focusableCount == views.size())) &&
-                (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())) {
+        if ((descendantFocusability == FOCUS_AFTER_DESCENDANTS) && focusSelf
+                && focusableCount == views.size()) {
             super.addFocusables(views, direction, focusableMode);
         }
     }
@@ -4208,9 +4220,9 @@
      * {@hide}
      */
     @Override
-    protected <T extends View> T findViewTraversal(@IdRes int id) {
+    protected View findViewTraversal(@IdRes int id) {
         if (id == mID) {
-            return (T) this;
+            return this;
         }
 
         final View[] where = mChildren;
@@ -4223,7 +4235,7 @@
                 v = v.findViewById(id);
 
                 if (v != null) {
-                    return (T) v;
+                    return v;
                 }
             }
         }
@@ -4235,9 +4247,9 @@
      * {@hide}
      */
     @Override
-    protected <T extends View> T findViewWithTagTraversal(Object tag) {
+    protected View findViewWithTagTraversal(Object tag) {
         if (tag != null && tag.equals(mTag)) {
-            return (T) this;
+            return this;
         }
 
         final View[] where = mChildren;
@@ -4250,7 +4262,7 @@
                 v = v.findViewWithTag(tag);
 
                 if (v != null) {
-                    return (T) v;
+                    return v;
                 }
             }
         }
@@ -4262,10 +4274,9 @@
      * {@hide}
      */
     @Override
-    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
-            View childToSkip) {
+    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
         if (predicate.apply(this)) {
-            return (T) this;
+            return this;
         }
 
         final View[] where = mChildren;
@@ -4278,7 +4289,7 @@
                 v = v.findViewByPredicate(predicate);
 
                 if (v != null) {
-                    return (T) v;
+                    return v;
                 }
             }
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9bfc260..9e8dda8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -7492,13 +7492,13 @@
         public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
                 Region interactiveRegion, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
-                int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+                int interrogatingPid, long interrogatingTid, MagnificationSpec spec, Bundle args) {
             ViewRootImpl viewRootImpl = mViewRootImpl.get();
             if (viewRootImpl != null && viewRootImpl.mView != null) {
                 viewRootImpl.getAccessibilityInteractionController()
                     .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
                             interactiveRegion, interactionId, callback, flags, interrogatingPid,
-                            interrogatingTid, spec);
+                            interrogatingTid, spec, args);
             } else {
                 // We cannot make the call and notify the caller so it does not wait.
                 try {
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index db2ea48..143c49a 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -554,7 +554,7 @@
     // Layer of indirection included to break dependency chain for testing
     public static class AccessibilityNodeRefresher {
         public boolean refreshNode(AccessibilityNodeInfo info, boolean bypassCache) {
-            return info.refresh(bypassCache);
+            return info.refresh(null, bypassCache);
         }
     }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 1543597..828583c 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -159,7 +159,7 @@
     public AccessibilityNodeInfo getRootInActiveWindow(int connectionId) {
         return findAccessibilityNodeInfoByAccessibilityId(connectionId,
                 AccessibilityNodeInfo.ACTIVE_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID,
-                false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
+                false, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS, null);
     }
 
     /**
@@ -259,7 +259,7 @@
      */
     public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId,
             int accessibilityWindowId, long accessibilityNodeId, boolean bypassCache,
-            int prefetchFlags) {
+            int prefetchFlags, Bundle arguments) {
         if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS) != 0
                 && (prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) == 0) {
             throw new IllegalArgumentException("FLAG_PREFETCH_SIBLINGS"
@@ -285,9 +285,8 @@
                 final long identityToken = Binder.clearCallingIdentity();
                 final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId(
                         accessibilityWindowId, accessibilityNodeId, interactionId, this,
-                        prefetchFlags, Thread.currentThread().getId());
+                        prefetchFlags, Thread.currentThread().getId(), arguments);
                 Binder.restoreCallingIdentity(identityToken);
-                // If the scale is zero the call has failed.
                 if (success) {
                     List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
                             interactionId);
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 1ef0d17..45302b6 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -779,6 +779,49 @@
         }
     }
 
+    /**
+     * Notifies that the accessibility button in the system's navigation area has been clicked
+     *
+     * @hide
+     */
+    public void notifyAccessibilityButtonClicked() {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return;
+            }
+        }
+        try {
+            service.notifyAccessibilityButtonClicked();
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while dispatching accessibility button click", re);
+        }
+    }
+
+    /**
+     * Notifies that the availability of the accessibility button in the system's navigation area
+     * has changed.
+     *
+     * @param available {@code true} if the accessibility button is available within the system
+     *                  navigation area, {@code false} otherwise
+     * @hide
+     */
+    public void notifyAccessibilityButtonAvailabilityChanged(boolean available) {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+            if (service == null) {
+                return;
+            }
+        }
+        try {
+            service.notifyAccessibilityButtonAvailabilityChanged(available);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error while dispatching accessibility button availability change", re);
+        }
+    }
+
     private IAccessibilityManager getServiceLocked() {
         if (mService == null) {
             tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 56d45b0..b0a11cd 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -16,6 +16,8 @@
 
 package android.view.accessibility;
 
+import static java.util.Collections.EMPTY_LIST;
+
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.Nullable;
@@ -517,6 +519,46 @@
      */
     public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
 
+    /**
+     * Key used to request and locate extra data for text character location. This key requests that
+     * an array of {@link android.graphics.RectF}s be added to the extras. This request is made with
+     * {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by this request are two
+     * integers: {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and
+     * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index must be valid
+     * inside the CharSequence returned by {@link #getText()}, and the length must be positive.
+     * <p>
+     * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this
+     * string as a key for {@link Bundle#getParcelableArray(String)}. The
+     * {@link android.graphics.RectF} will be null for characters that either do not exist or are
+     * off the screen.
+     *
+     * {@see #refreshWithExtraData(String, Bundle)}
+     */
+    public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY =
+            "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
+
+    /**
+     * Integer argument specifying the start index of the requested text location data. Must be
+     * valid inside the CharSequence returned by {@link #getText()}.
+     *
+     * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
+     */
+    public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX =
+            "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
+
+    /**
+     * Integer argument specifying the end index of the requested text location data. Must be
+     * positive.
+     *
+     * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
+     */
+    public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH =
+            "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
+
+    /** @hide */
+    public static final String EXTRA_DATA_REQUESTED_KEY =
+            "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";
+
     // Boolean attributes.
 
     private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
@@ -651,6 +693,7 @@
     private CharSequence mError;
     private CharSequence mContentDescription;
     private String mViewIdResourceName;
+    private ArrayList<String> mExtraDataKeys;
 
     private LongArray mChildNodeIds;
     private ArrayList<AccessibilityAction> mActions;
@@ -786,14 +829,14 @@
      *
      * @hide
      */
-    public boolean refresh(boolean bypassCache) {
+    public boolean refresh(Bundle arguments, boolean bypassCache) {
         enforceSealed();
         if (!canPerformRequestOverConnection(mSourceNodeId)) {
             return false;
         }
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
-                mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
+                mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments);
         if (refreshedInfo == null) {
             return false;
         }
@@ -804,15 +847,33 @@
 
     /**
      * Refreshes this info with the latest state of the view it represents.
-     * <p>
-     * <strong>Note:</strong> If this method returns false this info is obsolete
-     * since it represents a view that is no longer in the view tree and should
-     * be recycled.
-     * </p>
-     * @return Whether the refresh succeeded.
+     *
+     * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
+     * by this node is no longer in the view tree (and thus this node is obsolete and should be
+     * recycled).
      */
     public boolean refresh() {
-        return refresh(true);
+        return refresh(null, true);
+    }
+
+    /**
+     * Refreshes this info with the latest state of the view it represents, and request new
+     * data be added by the View.
+     *
+     * @param extraDataKey A bitmask of the extra data requested. Data that must be requested
+     *                     with this mechanism is generally expensive to retrieve, so should only be
+     *                     requested when needed. See
+     *                     {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
+     *                     {@link #getAvailableExtraData()}.
+     * @param args A bundle of arguments for the request. These depend on the particular request.
+     *
+     * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
+     * by this node is no longer in the view tree (and thus this node is obsolete and should be
+     * recycled).
+     */
+    public boolean refreshWithExtraData(String extraDataKey, Bundle args) {
+        args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey);
+        return refresh(args, true);
     }
 
     /**
@@ -872,7 +933,7 @@
         final long childId = mChildNodeIds.get(index);
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
-                childId, false, FLAG_PREFETCH_DESCENDANTS);
+                childId, false, FLAG_PREFETCH_DESCENDANTS, null);
     }
 
     /**
@@ -1263,6 +1324,45 @@
     }
 
     /**
+     * Get the extra data available for this node.
+     * <p>
+     * Some data that is useful for some accessibility services is expensive to compute, and would
+     * place undue overhead on apps to compute all the time. That data can be requested with
+     * {@link #refreshWithExtraData(String, Bundle)}.
+     *
+     * @return An unmodifiable list of keys corresponding to extra data that can be requested.
+     * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
+     */
+    public List<String> getAvailableExtraData() {
+        if (mExtraDataKeys != null) {
+            return Collections.unmodifiableList(mExtraDataKeys);
+        } else {
+            return EMPTY_LIST;
+        }
+    }
+
+    /**
+     * Set the extra data available for this node.
+     * <p>
+     * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that
+     * it will populate the node's extras with corresponding pieces of information in
+     * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}.
+     * <p>
+     * <strong>Note:</strong> Cannot be called from an
+     * {@link android.accessibilityservice.AccessibilityService}.
+     * This class is made immutable before being delivered to an AccessibilityService.
+     *
+     * @param extraDataKeys A list of types of extra data that are available.
+     * @see #getAvailableExtraData()
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setAvailableExtraData(List<String> extraDataKeys) {
+        enforceNotSealed();
+        mExtraDataKeys = new ArrayList<>(extraDataKeys);
+    }
+
+    /**
      * Sets the maximum text length, or -1 for no limit.
      * <p>
      * Typically used to indicate that an editable text field has a limit on
@@ -2658,6 +2758,14 @@
     }
 
     /**
+     * Check if a node has an extras bundle
+     * @hide
+     */
+    public boolean hasExtras() {
+        return mExtras != null;
+    }
+
+    /**
      * Gets the value of a boolean property.
      *
      * @param property The property.
@@ -2955,6 +3063,12 @@
         parcel.writeInt(mInputType);
         parcel.writeInt(mLiveRegion);
         parcel.writeInt(mDrawingOrderInParent);
+        if (mExtraDataKeys != null) {
+            parcel.writeInt(1);
+            parcel.writeStringList(mExtraDataKeys);
+        } else {
+            parcel.writeInt(0);
+        }
 
         if (mExtras != null) {
             parcel.writeInt(1);
@@ -3054,6 +3168,8 @@
         mInputType = other.mInputType;
         mLiveRegion = other.mLiveRegion;
         mDrawingOrderInParent = other.mDrawingOrderInParent;
+        mExtraDataKeys = other.mExtraDataKeys;
+
         if (other.mExtras != null) {
             mExtras = new Bundle(other.mExtras);
         } else {
@@ -3137,6 +3253,12 @@
         mDrawingOrderInParent = parcel.readInt();
 
         if (parcel.readInt() == 1) {
+            mExtraDataKeys = parcel.createStringArrayList();
+        } else {
+            mExtraDataKeys = null;
+        }
+
+        if (parcel.readInt() == 1) {
             mExtras = parcel.readBundle();
         } else {
             mExtras = null;
@@ -3455,7 +3577,7 @@
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
                 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
-                        | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+                        | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index abcbb70..722b659 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -102,6 +102,27 @@
     }
 
     /**
+     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
+     * additional data.
+     * <p>
+     * This method only needs to be implemented if a virtual view offers to provide additional
+     * data.
+     * </p>
+     *
+     * @param virtualViewId The virtual view id used to create the node
+     * @param info The info to which to add the extra data
+     * @param extraDataKey A key specifying the type of extra data to add to the info. The
+     *                     extra data should be added to the {@link Bundle} returned by
+     *                     the info's {@link AccessibilityNodeInfo#getExtras} method.
+     * @param arguments A {@link Bundle} holding any arguments relevant for this request.
+     *
+     * @see AccessibilityNodeInfo#setExtraAvailableData
+     */
+    public void addExtraDataToAccessibilityNodeInfo(
+            int virtualViewId, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
+    }
+
+    /**
      * Performs an accessibility action on a virtual view, i.e. a descendant of the
      * host View, with the given <code>virtualViewId</code> or the host View itself
      * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 3287298..c390406 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -183,7 +183,7 @@
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
                 mId, AccessibilityNodeInfo.ROOT_NODE_ID,
-                true, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
+                true, AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS, null);
     }
 
     /**
@@ -209,7 +209,7 @@
 
         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
-                mParentId, mAnchorId, true, 0);
+                mParentId, mAnchorId, true, 0, null);
     }
 
     /**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index cecc4af..4c0fdfd 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -33,7 +33,8 @@
 
     void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, in Region bounds,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
-        int interrogatingPid, long interrogatingTid, in MagnificationSpec spec);
+        int interrogatingPid, long interrogatingTid, in MagnificationSpec spec,
+        in Bundle arguments);
 
     void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId,
         in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback,
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 136bbbe..8fde47a 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -59,6 +59,10 @@
 
     IBinder getWindowToken(int windowId, int userId);
 
+    void notifyAccessibilityButtonClicked();
+
+    void notifyAccessibilityButtonAvailabilityChanged(boolean available);
+
     // Requires WRITE_SECURE_SETTINGS
     void performAccessibilityShortcut();
 
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index f2f522d..6c20f07 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -16,9 +16,12 @@
 
 package android.view.autofill;
 
+import static android.view.autofill.Helper.VERBOSE;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.service.autofill.IAutoFillManagerService;
 import android.util.Log;
@@ -28,95 +31,184 @@
  * App entry point to the AutoFill Framework.
  */
 // TODO(b/33197203): improve this javadoc
+//TODO(b/33197203): restrict manager calls to activity
 public final class AutoFillManager {
 
     private static final String TAG = "AutoFillManager";
-    private static final boolean DEBUG = true; // TODO(b/33197203): change to false once stable
 
-    /**
-     * Flag used to show the auto-fill UI affordance for a view.
-     */
-    public static final int FLAG_UPDATE_UI_SHOW = 0x1;
-
-    /**
-     * Flag used to hide the auto-fill UI affordance for a view.
-     */
-    public static final int FLAG_UPDATE_UI_HIDE = 0x2;
+    /** @hide */ public static final int FLAG_START_SESSION = 0x1;
+    /** @hide */ public static final int FLAG_FOCUS_GAINED = 0x2;
+    /** @hide */ public static final int FLAG_FOCUS_LOST = 0x4;
+    /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x8;
 
     private final IAutoFillManagerService mService;
+    private final Context mContext;
+
+    private AutoFillSession mSession;
 
     /**
      * @hide
      */
-    public AutoFillManager(@SuppressWarnings("unused") Context context,
-            IAutoFillManagerService service) {
+    public AutoFillManager(Context context, IAutoFillManagerService service) {
+        mContext = context;
         mService = service;
     }
 
     /**
-     * Updates the auto-fill bar for a given {@link View}.
+     * Called to indicate the focus on an auto-fillable {@link View} changed.
      *
-     * <b>Typically called twice, with different flags ({@link #FLAG_UPDATE_UI_SHOW} and
-     * {@link #FLAG_UPDATE_UI_HIDE} respectively), as the user "entered" and "exited" a view.
-     *
-     * @param view view to be updated.
-     * @param flags either {@link #FLAG_UPDATE_UI_SHOW} or
-     * {@link #FLAG_UPDATE_UI_HIDE}.
+     * @param view view whose focus changed.
+     * @param gainFocus whether focus was gained or lost.
      */
-    public void updateAutoFillInput(View view, int flags) {
+    public void focusChanged(View view, boolean gainFocus) {
+        if (mSession == null) {
+            // Starts new session.
+            final Rect bounds = new Rect();
+            view.getBoundsOnScreen(bounds);
+            final AutoFillId id = getAutoFillId(view);
+            final AutoFillValue value = view.getAutoFillValue();
+            startSession(id, bounds, value);
+            return;
+        }
+
+        if (!mSession.isEnabled()) {
+            // Auto-fill is disabled for this session.
+            return;
+        }
+
+        // Update focus on existing session.
         final Rect bounds = new Rect();
         view.getBoundsOnScreen(bounds);
-
-        requestAutoFill(getAutoFillId(view), bounds, flags);
-    }
-
-    /**
-     * Updates the auto-fill bar for a virtual child of a given {@link View}.
-     *
-     * <b>Typically called twice, with different flags ({@link #FLAG_UPDATE_UI_SHOW} and
-     * {@link #FLAG_UPDATE_UI_HIDE} respectively), as the user "entered" and "exited" a view.
-     *
-     * @param parent parent view.
-     * @param childId id identifying the virtual child inside the parent view.
-     * @param bounds absolute boundaries of the child in the window (could be {@code null} when
-     * flag is {@link #FLAG_UPDATE_UI_HIDE}.
-     * @param flags either {@link #FLAG_UPDATE_UI_SHOW} or
-     * {@link #FLAG_UPDATE_UI_HIDE}.
-     */
-    public void updateAutoFillInput(View parent, int childId, @Nullable Rect bounds,
-            int flags) {
-        requestAutoFill(new AutoFillId(parent.getAccessibilityViewId(), childId), bounds, flags);
-    }
-
-    /**
-     * Notifies the framework that the value of a view changed.
-     * @param view view whose value was updated
-     * @param value new value.
-     */
-    public void onValueChanged(View view, AutoFillValue value) {
-        // TODO(b/33197203): optimize it by not calling service when the view does not belong to
-        // the session.
         final AutoFillId id = getAutoFillId(view);
-        if (DEBUG) Log.v(TAG, "onValueChanged(): id=" + id + ", value=" + value);
+        final AutoFillValue value = view.getAutoFillValue();
+        updateSession(id, bounds, value, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST);
+    }
+
+    /**
+     * Called to indicate the focus on an auto-fillable virtual {@link View} changed.
+     *
+     * @param parent parent view whose focus changed.
+     * @param childId id identifying the virtual child inside the parent view.
+     * @param bounds child boundaries, relative to the top window.
+     * @param value current value of the child; can be {@code null} when focus is lost, but must be
+     *            set when focus is gained.
+     * @param gainFocus whether focus was gained or lost.
+     */
+    public void virtualFocusChanged(View parent, int childId, Rect bounds,
+            @Nullable AutoFillValue value, boolean gainFocus) {
+        if (mSession == null) {
+            // Starts new session.
+            final AutoFillId id = getAutoFillId(parent, childId);
+            startSession(id, bounds, value);
+            return;
+        }
+
+        if (!mSession.isEnabled()) {
+            // Auto-fill is disabled for this session.
+            return;
+        }
+
+        // Update focus on existing session.
+        final AutoFillId id = getAutoFillId(parent, childId);
+        updateSession(id, bounds, value, gainFocus ? FLAG_FOCUS_GAINED : FLAG_FOCUS_LOST);
+    }
+
+    /**
+     * Called to indicate the value of an auto-fillable {@link View} changed.
+     *
+     * @param view view whose focus changed.
+     */
+    public void valueChanged(View view) {
+        if (mSession == null) return;
+
+        final AutoFillId id = getAutoFillId(view);
+        final AutoFillValue value = view.getAutoFillValue();
+        updateSession(id, null, value, FLAG_VALUE_CHANGED);
+    }
+
+
+    /**
+     * Called to indicate the value of an auto-fillable virtual {@link View} changed.
+     *
+     * @param parent parent view whose value changed.
+     * @param childId id identifying the virtual child inside the parent view.
+     * @param value new value of the child.
+     */
+    public void virtualValueChanged(View parent, int childId, AutoFillValue value) {
+        if (mSession == null) return;
+
+        final AutoFillId id = getAutoFillId(parent, childId);
+        updateSession(id, null, value, FLAG_VALUE_CHANGED);
+    }
+
+    /**
+     * Called to indicate the current auto-fill context should be reset.
+     *
+     * <p>For example, when a virtual view is rendering an {@code HTML} page with a form, it should
+     * call this method after the form is submitted and another page is rendered.
+     */
+    public void reset() {
+        if (mSession == null) return;
+
+        final IBinder activityToken = mSession.mToken.get();
+        if (activityToken == null) {
+            Log.wtf(TAG, "finishSession(): token already GC'ed");
+            return;
+        }
         try {
-            mService.onValueChanged(id, value);
+            mService.finishSession(activityToken);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } finally {
+            mSession = null;
         }
     }
 
+    /**
+     * Gets the current session, if any.
+     *
+     * @hide
+     */
+    @Nullable
+    public AutoFillSession getSession() {
+        return mSession;
+    }
+
     private AutoFillId getAutoFillId(View view) {
         return new AutoFillId(view.getAccessibilityViewId());
     }
 
-    private void requestAutoFill(AutoFillId id, Rect bounds, int flags) {
-        // TODO(b/33197203): optimize it by not calling service when the view does not belong to
-        // the session.
-        if (DEBUG) {
-            Log.v(TAG, "requestAutoFill(): id=" + id + ", bounds=" + bounds + ", flags=" + flags);
+    private AutoFillId getAutoFillId(View parent, int childId) {
+        return new AutoFillId(parent.getAccessibilityViewId(), childId);
+    }
+
+    private void startSession(AutoFillId id, Rect bounds, AutoFillValue value) {
+        if (VERBOSE) {
+            Log.v(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value);
+        }
+
+        final IBinder activityToken = mContext.getActivityToken();
+        mSession = new AutoFillSession(this, activityToken);
+        final IBinder appCallback = mSession.getCallback().asBinder();
+        try {
+            mService.startSession(activityToken, appCallback, id, bounds, value);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private void updateSession(AutoFillId id, Rect bounds, AutoFillValue value, int flags) {
+        if (VERBOSE) {
+            Log.v(TAG, "updateSession(): id=" + id + ", bounds=" + bounds + ", value=" + value
+                    + ", flags=" + flags);
+        }
+
+        final IBinder activityToken = mSession.mToken.get();
+        if (activityToken == null) {
+            return;
         }
         try {
-            mService.requestAutoFill(id, bounds, flags);
+            mService.updateSession(activityToken, id, bounds, value, flags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/view/autofill/AutoFillSession.java b/core/java/android/view/autofill/AutoFillSession.java
index eec7a82..e10ba37 100644
--- a/core/java/android/view/autofill/AutoFillSession.java
+++ b/core/java/android/view/autofill/AutoFillSession.java
@@ -19,13 +19,13 @@
 import static android.view.autofill.Helper.DEBUG;
 
 import android.app.Activity;
-import android.os.RemoteException;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.IBinder;
 import android.service.autofill.IAutoFillAppCallback;
 import android.util.Log;
 import android.view.View;
 
-import com.android.internal.annotations.GuardedBy;
-
 import java.lang.ref.WeakReference;
 
 /**
@@ -38,8 +38,16 @@
     private static final String TAG = "AutoFillSession";
 
     private final IAutoFillAppCallback mCallback = new IAutoFillAppCallback.Stub() {
+
         @Override
-        public void autoFill(Dataset dataset) throws RemoteException {
+        public void enableSession() {
+            if (DEBUG) Log.d(TAG, "enableSession()");
+
+            mEnabled = true;
+        }
+
+        @Override
+        public void autoFill(Dataset dataset) {
             final Activity activity = mActivity.get();
             if (activity == null) {
                 if (DEBUG) Log.d(TAG, "autoFill(): activity already GCed");
@@ -49,12 +57,10 @@
             // dataset.extras to service
             activity.runOnUiThread(() -> {
                 final View root = activity.getWindow().getDecorView().getRootView();
-                for (DatasetField field : dataset.getFields()) {
-                    final AutoFillId id = field.getId();
-                    if (id == null) {
-                        Log.w(TAG, "autoFill(): null id on " + field);
-                        continue;
-                    }
+                final int itemCount = dataset.getFieldIds().size();
+                for (int i = 0; i < itemCount; i++) {
+                    final AutoFillId id = dataset.getFieldIds().get(i);
+                    final AutoFillValue value = dataset.getFieldValues().get(i);
                     final int viewId = id.getViewId();
                     final View view = root.findViewByAccessibilityIdTraversal(viewId);
                     if (view == null) {
@@ -65,10 +71,8 @@
                     // TODO(b/33197203): handle protected value (like credit card)
                     if (id.isVirtual()) {
                         // Delegate virtual fields.
-                        setAutoFillDelegateCallback();
                         final VirtualViewDelegate delegate = view
-                                .getAutoFillVirtualViewDelegate(
-                                        mAutoFillDelegateCallback);
+                                .getAutoFillVirtualViewDelegate();
                         if (delegate == null) {
                             Log.w(TAG, "autoFill(): cannot fill virtual " + id
                                     + "; no VirtualViewDelegate for view "
@@ -79,40 +83,84 @@
                             Log.d(TAG, "autoFill(): delegating " + id
                                     + " to VirtualViewDelegate  " + delegate);
                         }
-                        delegate.autoFill(id.getVirtualChildId(), field.getValue());
+                        delegate.autoFill(id.getVirtualChildId(), value);
                     } else {
                         // Handle non-virtual fields itself.
-                        view.autoFill(field.getValue());
+                        view.autoFill(value);
                     }
                 }
             });
         }
+
+        @Override
+        public void startIntentSender(IntentSender intent, Intent fillInIntent) {
+            final Activity activity = mActivity.get();
+            if (activity != null) {
+                activity.runOnUiThread(() -> {
+                    try {
+                        activity.startIntentSender(intent, fillInIntent, 0, 0, 0);
+                    } catch (IntentSender.SendIntentException e) {
+                        Log.e(TAG, "startIntentSender() failed for intent:" + intent, e);
+                    }
+                });
+            }
+        }
     };
 
-    private final WeakReference<Activity> mActivity;
+    private final AutoFillManager mAfm;
+    private WeakReference<Activity> mActivity;
 
-    @GuardedBy("this")
-    private VirtualViewDelegate.Callback mAutoFillDelegateCallback;
+    // Reference to the token, which is used by the server.
+    final WeakReference<IBinder> mToken;
 
-    public AutoFillSession(Activity activity) {
+    private boolean mEnabled;
+
+    public AutoFillSession(AutoFillManager afm, IBinder token) {
+        mToken = new WeakReference<>(token);
+        mAfm = afm;
+    }
+
+    /**
+     * Called by the {@link Activity} when it was asked to provider auto-fill data.
+     */
+    public void attachActivity(Activity activity) {
+        if (mActivity != null) {
+            Log.w(TAG, "attachActivity(): already attached");
+            return;
+        }
         mActivity = new WeakReference<>(activity);
     }
 
+    /**
+     * Checks whether auto-fill is enabled for this session, as decided by the
+     * {@code AutoFillManagerService}.
+     */
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Notifies the manager that a session finished.
+     */
+    // TODO(b/33197203): hook it to other lifecycle events like fragments transition
+    public void finishSession() {
+        if (mAfm != null) {
+            try {
+                mAfm.reset();
+            } catch (RuntimeException e) {
+                Log.w(TAG, "Failed to finish session for " + mToken.get() + ": " + e);
+            }
+        }
+    }
+
     public IAutoFillAppCallback getCallback() {
         return mCallback;
     }
 
-    /**
-     * Lazily sets the {@link #mAutoFillDelegateCallback}.
-     */
-    private void setAutoFillDelegateCallback() {
-        synchronized (this) {
-            if (mAutoFillDelegateCallback == null) {
-                mAutoFillDelegateCallback = new VirtualViewDelegate.Callback() {
-                    // TODO(b/33197203): implement
-                };
-            }
-        }
-    }
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
 
+        return "AutoFillSession[activityoken=" + mToken.get() + "]";
+    }
 }
diff --git a/core/java/android/view/autofill/AutoFillValue.java b/core/java/android/view/autofill/AutoFillValue.java
index 57b23ef..b31f4af 100644
--- a/core/java/android/view/autofill/AutoFillValue.java
+++ b/core/java/android/view/autofill/AutoFillValue.java
@@ -18,6 +18,7 @@
 
 import static android.view.autofill.Helper.DEBUG;
 
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.view.View;
@@ -32,12 +33,12 @@
  */
 public final class AutoFillValue implements Parcelable {
 
-    private final CharSequence mText;
+    private final String mText;
     private final int mListIndex;
     private final boolean mToggle;
 
     private AutoFillValue(CharSequence text, int listIndex, boolean toggle) {
-        mText = text;
+        mText = (text == null) ? null : text.toString();
         mListIndex = listIndex;
         mToggle = toggle;
     }
@@ -74,6 +75,32 @@
     /////////////////////////////////////
 
     @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + mListIndex;
+        result = prime * result + ((mText == null) ? 0 : mText.hashCode());
+        result = prime * result + (mToggle ? 1231 : 1237);
+        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 AutoFillValue other = (AutoFillValue) obj;
+        if (mListIndex != other.mListIndex) return false;
+        if (mText == null) {
+            if (other.mText != null) return false;
+        } else {
+            if (!mText.equals(other.mText)) return false;
+        }
+        if (mToggle != other.mToggle) return false;
+        return true;
+    }
+
+    @Override
     public String toString() {
         if (!DEBUG) return super.toString();
 
@@ -92,13 +119,13 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeCharSequence(mText);
+        parcel.writeString(mText);
         parcel.writeInt(mListIndex);
         parcel.writeInt(mToggle ? 1 : 0);
     }
 
     private AutoFillValue(Parcel parcel) {
-        mText = parcel.readCharSequence();
+        mText = parcel.readString();
         mListIndex = parcel.readInt();
         mToggle = parcel.readInt() == 1;
     }
@@ -127,8 +154,9 @@
      * <p>See {@link AutoFillType#isText()} for more info.
      */
     // TODO(b/33197203): use cache
-    public static AutoFillValue forText(CharSequence value) {
-        return new AutoFillValue(value, 0, false);
+    @Nullable
+    public static AutoFillValue forText(@Nullable CharSequence value) {
+        return value == null ? null : new AutoFillValue(value, 0, false);
     }
 
     /**
diff --git a/core/java/android/view/autofill/Dataset.java b/core/java/android/view/autofill/Dataset.java
index 18a08f9..2708358 100644
--- a/core/java/android/view/autofill/Dataset.java
+++ b/core/java/android/view/autofill/Dataset.java
@@ -17,12 +17,12 @@
 package android.view.autofill;
 
 import static android.view.autofill.Helper.DEBUG;
-import static android.view.autofill.Helper.append;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.assist.AssistStructure.ViewNode;
-import android.hardware.fingerprint.FingerprintManager.CryptoObject;
+import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,8 +30,6 @@
 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}.
@@ -44,221 +42,184 @@
  *   <li>An optional {@link Bundle} with extras (used only by the service creating it).
  * </ol>
  *
- * See {@link FillResponse} for examples.
+ * @see FillResponse for examples.
  */
 public final class Dataset implements Parcelable {
-
+    private final String mId;
     private final CharSequence mName;
-    private final ArrayList<DatasetField> mFields;
+    private final ArrayList<AutoFillId> mFieldIds;
+    private final ArrayList<AutoFillValue> mFieldValues;
     private final Bundle mExtras;
-    private final int mFlags;
-    private final boolean mRequiresAuth;
-    private final boolean mHasCryptoObject;
-    private final long mCryptoOpId;
+    private final IntentSender mAuthentication;
 
-    private Dataset(Dataset.Builder builder) {
+    private Dataset(Builder builder) {
+        mId = builder.mId;
         mName = builder.mName;
-        // TODO(b/33197203): make an immutable copy of mFields?
-        mFields = builder.mFields;
+        mFieldIds = builder.mFieldIds;
+        mFieldValues = builder.mFieldValues;
         mExtras = builder.mExtras;
-        mFlags = builder.mFlags;
-        mRequiresAuth = builder.mRequiresAuth;
-        mHasCryptoObject = builder.mHasCryptoObject;
-        mCryptoOpId = builder.mCryptoOpId;
+        mAuthentication = builder.mAuthentication;
     }
 
     /** @hide */
-    public CharSequence getName() {
+    public @NonNull String getId() {
+        return mId;
+    }
+
+    /** @hide */
+    public @NonNull CharSequence getName() {
         return mName;
     }
 
     /** @hide */
-    public List<DatasetField> getFields() {
-        return mFields;
+    public @Nullable ArrayList<AutoFillId> getFieldIds() {
+        return mFieldIds;
     }
 
     /** @hide */
-    public Bundle getExtras() {
+    public @Nullable ArrayList<AutoFillValue> getFieldValues() {
+        return mFieldValues;
+    }
+
+    /** @hide */
+    public @Nullable Bundle getExtras() {
         return mExtras;
     }
 
     /** @hide */
-    public int getFlags() {
-        return mFlags;
-    }
-
-    /** @hide */
-    public boolean isAuthRequired() {
-        return mRequiresAuth;
+    public @Nullable IntentSender getAuthentication() {
+        return mAuthentication;
     }
 
     /** @hide */
     public boolean isEmpty() {
-        return mFields.isEmpty();
-    }
-
-    /** @hide */
-    public boolean hasCryptoObject() {
-        return mHasCryptoObject;
-    }
-
-    /** @hide */
-    public long getCryptoObjectOpId() {
-        return mCryptoOpId;
+        return mFieldIds == null || mFieldIds.isEmpty();
     }
 
     @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)
-            .append(", flags=").append(mFlags)
-            .append(", requiresAuth: ").append(mRequiresAuth)
-            .append(", hasCrypto: ").append(mHasCryptoObject);
+        final StringBuilder builder = new StringBuilder("Dataset [id=").append(mId)
+                .append(", name=").append(mName)
+                .append(", fieldIds=").append(mFieldIds)
+                .append(", fieldValues=").append(mFieldValues)
+                .append(", hasAuthentication=").append(mAuthentication != null)
+                .append(", hasExtras=").append(mExtras != null);
         return builder.append(']').toString();
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final Dataset other = (Dataset) obj;
+        if (mId == null) {
+            if (other.mId != null) {
+                return false;
+            }
+        } else if (!mId.equals(other.mId)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return mId != null ? mId.hashCode() : 0;
+    }
+
     /**
-     * A builder for {@link Dataset} objects.
+     * A builder for {@link Dataset} objects. You must to provide at least
+     * one value for a field or set an authentication intent.
      */
     public static final class Builder {
+        private String mId;
         private CharSequence mName;
-        private final ArrayList<DatasetField> mFields = new ArrayList<>();
+        private ArrayList<AutoFillId> mFieldIds;
+        private ArrayList<AutoFillValue> mFieldValues;
         private Bundle mExtras;
-        private int mFlags;
-        private boolean mRequiresAuth;
-        private boolean mHasCryptoObject;
-        private long mCryptoOpId;
+        private IntentSender mAuthentication;
+        private boolean mDestroyed;
+
+        /** @hide */
+        // TODO(b/33197203): Remove once GCore migrates
+        public Builder(@NonNull CharSequence name) {
+            this(String.valueOf(System.currentTimeMillis()), name);
+        }
 
         /**
          * Creates a new builder.
          *
+         * @param id A required id to identify this dataset for future interactions related to it.
          * @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
+         * the first field in the dataset (like username or email address) or a user-provided name
          * (like "My Work Address").
          */
-        public Builder(CharSequence name) {
+        public Builder(@NonNull String id, @NonNull CharSequence name) {
+            mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty or null");
             mName = Preconditions.checkStringNotEmpty(name, "name cannot be empty or null");
         }
 
         /**
-         * Requires dataset authentication through the {@link
-         * android.service.autofill.AutoFillService} before auto-filling the activity with this
-         * dataset.
+         * Requires a dataset authentication before auto-filling the activity with this dataset.
          *
-         * <p>This method is typically called when the device (or the service) does not support
-         * fingerprint authentication (and hence it cannot use {@link
-         * #requiresFingerprintAuthentication(CryptoObject, Bundle, int)}) or when the service needs
-         * to use a custom authentication UI for the dataset. For example, when a dataset contains
-         * credit card information (such as number, expiration date, and verification code), the
-         * service displays an authentication dialog asking for the verification code to unlock the
-         * rest of the data).
+         * <p>This method is called when you need to provide an authentication
+         * UI for the dataset. For example, when a dataset contains credit card information
+         * (such as number, expiration date, and verification code), you can display UI
+         * asking for the verification code to before filing in the data). Even if the
+         * dataset is completely populated the system will launch the specified authentication
+         * intent and will need your approval to fill it in. Since the dataset is "locked"
+         * until the user authenticates it, typically this dataset name is masked
+         * (for example, "VISA....1234"). Typically you would want to store the dataset
+         * labels non-encypted and the actual sensitive data encrypted and not in memory.
+         * This allows showing the labels in the UI while involving the user if one of
+         * the items with these labels is chosen. Note that if you use sensitive data as
+         * a label, for example an email address, then it should also be encrypted.
+         *</p>
          *
-         * <p>Since the dataset is "locked" until the user authenticates it, typically this dataset
-         * name is masked (for example, "VISA....1234").
+         * <p>When a user selects this dataset, the system triggers the provided intent
+         * whose extras will have the {@link android.content.Intent#EXTRA_AUTO_FILL_ITEM_ID id}
+         * of the {@link android.view.autofill.Dataset dataset} to authenticate, the {@link
+         * android.content.Intent#EXTRA_AUTO_FILL_EXTRAS extras} associated with this
+         * dataset, and a {@link android.content.Intent#EXTRA_AUTO_FILL_CALLBACK callback}
+         * to dispatch the authentication result.</p>
          *
-         * <p>When the user selects this dataset, the Android System calls {@link
-         * android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
-         * passing {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_REQUESTED} in
-         * the flags and the same {@code extras} passed to this method. The service can then
-         * displays its custom authentication UI, and then call the proper method on {@link
-         * android.service.autofill.FillCallback} depending on the authentication result and whether
-         * this dataset already contains the fields needed to auto-fill the activity:
+         * <p>Once you complete your authentication flow you should use the provided callback
+         * to notify for a failure or a success. In case of a success you need to provide
+         * only the fully populated dataset that is being authenticated. For example, if you
+         * provided a {@link FillResponse} with two {@link Dataset}s and marked that
+         * only the first dataset needs an authentication then in the provided response
+         * you need to provide only the fully populated dataset being authenticated instead
+         * of both of them.
+         * </p>
          *
-         * <ul>
-         *   <li>If authentication failed, call
-         *   {@link android.service.autofill.FillCallback#onDatasetAuthentication(Dataset,
-         *       int)} passing {@link
-         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} in the flags.
-         *   <li>If authentication succeeded and this datast is empty (no fields), call {@link
-         *       android.service.autofill.FillCallback#onSuccess(FillResponse)} with a new dataset
-         *       (with the proper fields).
-         *   <li>If authentication succeeded and this response is not empty, call {@link
-         *       android.service.autofill.FillCallback#onDatasetAuthentication(Dataset, int)}
-         *       passing
-         *       {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS} in the
-         *       {@code flags} and {@code null} as the {@code dataset}.
-         * </ul>
+         * <p>The indent sender mechanism allows you to have your authentication UI
+         * implemented as an activity or a service or a receiver. However, the recommended
+         * way is to do this is with an activity which the system will start in the
+         * filled activity's task meaning it will properly work with back, recent apps, and
+         * free-form multi-window, while avoiding the need for the "draw on top of other"
+         * apps special permission. You can still theme your authentication activity's
+         * UI to look like a dialog if desired.</p>
          *
-         * @param extras when set, will be passed back in the {@link
-         *     android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle,
-         *     int)}, call so it could be used by the service to handle state.
-         * @param flags optional parameters, currently ignored.
+         * <p></><strong>Note:</strong> Do not make the provided intent sender
+         * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
+         * platform needs to fill in the authentication arguments.</p>
+         *
+         * @param authentication Intent to trigger your authentication flow.
+         *
+         * @see android.app.PendingIntent#getIntentSender()
          */
-        public Builder requiresCustomAuthentication(@Nullable Bundle extras, int flags) {
-            return requiresAuthentication(null, extras, flags);
-        }
-
-        /**
-         * Requires dataset authentication through the Fingerprint sensor before auto-filling the
-         * activity with this dataset.
-         *
-         * <p>This method is typically called when the dataset contains sensitive information (for
-         * example, credit card information) and the provider requires the user to re-authenticate
-         * before using it.
-         *
-         * <p>Since the dataset is "locked" until the user authenticates it, typically this dataset
-         * name is masked (for example, "VISA....1234").
-         *
-         * <p>When the user selects this dataset, the Android System displays an UI affordance
-         * asking the user to use the fingerprint sensor unlock the dataset, and what happens after
-         * a successful fingerprint authentication depends on whether the dataset is empty (no
-         * fields, only the masked name) or not:
-         *
-         * <ul>
-         *   <li>If it's empty, the Android System will call {@link
-         *       android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle,
-         *       int)} passing {@link
-         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}} in the
-         *       flags.
-         *   <li>If it's not empty, the activity will be auto-filled with its data.
-         * </ul>
-         *
-         * <p>If the fingerprint authentication fails, the Android System will call {@link
-         * android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
-         * passing {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} in the
-         * flags.
-         *
-         * <p><strong>NOTE: </note> the {@link android.service.autofill.AutoFillService} should use
-         * the {@link android.hardware.fingerprint.FingerprintManager} to check if fingerpint
-         * authentication is available before using this method, and use other alternatives (such as
-         * {@link #requiresCustomAuthentication(Bundle, int)}) if it is not: if this method is
-         * called when fingerprint is not available, Android System will call {@link
-         * android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
-         * passing {@link
-         * android.service.autofill.AutoFillService#FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}
-         * in the flags, but it would be wasting system resources (and worsening the user
-         * experience) in the process.
-         *
-         * @param crypto object that will be authenticated.
-         * @param extras when set, will be passed back in the {@link
-         *     android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
-         *     call so it could be used by the service to handle state.
-         * @param flags optional parameters, currently ignored.
-         */
-        public Builder requiresFingerprintAuthentication(CryptoObject crypto,
-                @Nullable Bundle extras, int flags) {
-            // TODO(b/33197203): should we allow crypto to be null?
-            Preconditions.checkArgument(crypto != null, "must pass a CryptoObject");
-            return requiresAuthentication(crypto, extras, flags);
-        }
-
-        private Builder requiresAuthentication(CryptoObject cryptoObject, Bundle extras,
-                int flags) {
-            // There can be only one!
-            Preconditions.checkState(!mRequiresAuth,
-                    "requires-authentication methods already called");
-            // TODO(b/33197203): make sure that either this method or setExtras() is called, but
-            // not both
-            mExtras = extras;
-            mFlags = flags;
-            mRequiresAuth = true;
-            if (cryptoObject != null) {
-                mHasCryptoObject = true;
-                mCryptoOpId = cryptoObject.getOpId();
-            }
+        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) {
+            throwIfDestroyed();
+            mAuthentication = authentication;
             return this;
         }
 
@@ -268,41 +229,55 @@
          * @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));
+        public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
+            throwIfDestroyed();
+            Preconditions.checkNotNull(id, "id cannot be null");
+            Preconditions.checkNotNull(value, "value cannot be null");
+            if (mFieldIds != null) {
+                final int existingIdx = mFieldIds.indexOf(id);
+                if (existingIdx >= 0) {
+                    mFieldValues.set(existingIdx, value);
+                    return this;
+                }
+            } else {
+                mFieldIds = new ArrayList<>();
+                mFieldValues = new ArrayList<>();
+            }
+            mFieldIds.add(id);
+            mFieldValues.add(value);
             return this;
         }
 
         /**
-         * Creates a new {@link Dataset} instance.
+         * Sets a {@link Bundle} that will be passed to subsequent APIs that
+         * manipulate this dataset. For example, they are passed in as {@link
+         * android.content.Intent#EXTRA_AUTO_FILL_EXTRAS extras} to your
+         * authentication flow.
          */
-        public Dataset build() {
+        public @NonNull Builder setExtras(@Nullable Bundle extras) {
+            throwIfDestroyed();
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Creates a new {@link Dataset} instance. You should not interact
+         * with this builder once this method is called.
+         */
+        public @NonNull Dataset build() {
+            throwIfDestroyed();
+            mDestroyed = true;
+            if (mFieldIds == null && mAuthentication == null) {
+                throw new IllegalArgumentException(
+                        "at least one value or an authentication must be set");
+            }
             return new Dataset(this);
         }
 
-        /**
-         * Sets a {@link Bundle} that will be passed to subsequent calls to
-         * {@link android.service.autofill.AutoFillService} methods such as
- * {@link android.service.autofill.AutoFillService#onSaveRequest(android.app.assist.AssistStructure,
-         * Bundle, android.service.autofill.SaveCallback)}, using
-         * {@link android.service.autofill.AutoFillService#EXTRA_DATASET_EXTRAS} as the key.
-         *
-         * <p>It can be used to keep service state in between calls.
-         */
-        public Builder setExtras(Bundle extras) {
-            // TODO(b/33197203): make sure that either this method or the requires-Authentication
-            // ones are called, but not both
-            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);
+        private void throwIfDestroyed() {
+            if (mDestroyed) {
+                throw new IllegalStateException("Already called #build()");
+            }
         }
     }
 
@@ -317,32 +292,33 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mId);
         parcel.writeCharSequence(mName);
-        parcel.writeList(mFields);
+        parcel.writeTypedArrayList(mFieldIds, 0);
+        parcel.writeTypedArrayList(mFieldValues, 0);
         parcel.writeBundle(mExtras);
-        parcel.writeInt(mFlags);
-        parcel.writeInt(mRequiresAuth ? 1 : 0);
-        parcel.writeInt(mHasCryptoObject ? 1 : 0);
-        if (mHasCryptoObject) {
-            parcel.writeLong(mCryptoOpId);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private Dataset(Parcel parcel) {
-        mName = parcel.readCharSequence();
-        mFields = parcel.readArrayList(null);
-        mExtras = parcel.readBundle();
-        mFlags = parcel.readInt();
-        mRequiresAuth = parcel.readInt() == 1;
-        mHasCryptoObject = parcel.readInt() == 1;
-        mCryptoOpId = mHasCryptoObject ? parcel.readLong() : 0;
+        parcel.writeParcelable(mAuthentication, flags);
     }
 
     public static final Parcelable.Creator<Dataset> CREATOR = new Parcelable.Creator<Dataset>() {
         @Override
-        public Dataset createFromParcel(Parcel source) {
-            return new Dataset(source);
+        public Dataset createFromParcel(Parcel parcel) {
+            // Always go through the builder to ensure the data ingested by
+            // the system obeys the contract of the builder to avoid attacks
+            // using specially crafted parcels.
+            final Builder builder = new Builder(parcel.readString(), parcel.readCharSequence());
+            final ArrayList<AutoFillId> ids = parcel.readTypedArrayList(null);
+            final ArrayList<AutoFillValue> values = parcel.readTypedArrayList(null);
+            final int idCount = (ids != null) ? ids.size() : 0;
+            final int valueCount = (values != null) ? values.size() : 0;
+            for (int i = 0; i < idCount; i++) {
+                AutoFillId id = ids.get(i);
+                AutoFillValue value = (valueCount > i) ? values.get(i) : null;
+                builder.setValue(id, value);
+            }
+            builder.setExtras(parcel.readBundle());
+            builder.setAuthentication(parcel.readParcelable(null));
+            return builder.build();
         }
 
         @Override
diff --git a/core/java/android/view/autofill/DatasetField.java b/core/java/android/view/autofill/DatasetField.java
deleted file mode 100644
index c6b92ac..0000000
--- a/core/java/android/view/autofill/DatasetField.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.autofill;
-
-import static android.view.autofill.Helper.DEBUG;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @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/view/autofill/FillResponse.java b/core/java/android/view/autofill/FillResponse.java
index 48dbb84..596a06c 100644
--- a/core/java/android/view/autofill/FillResponse.java
+++ b/core/java/android/view/autofill/FillResponse.java
@@ -16,36 +16,30 @@
 package android.view.autofill;
 
 import static android.view.autofill.Helper.DEBUG;
-import static android.view.autofill.Helper.append;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
-import android.hardware.fingerprint.FingerprintManager.CryptoObject;
+import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.service.autofill.FillCallback;
+import android.util.ArraySet;
 
 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
  * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} request.
+ * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} and
+ * authentication requests.
  *
  * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
- * fields that can be auto-filled together, and the Android System displays a dataset picker UI
+ * fields that can be auto-filled together, and the Android system displays a dataset picker UI
  * affordance that the user must use before the {@link Activity} is filled with the dataset.
  *
  * <p>For example, for a login page with username/password where the user only has one account in
- * the service, the response could be:
+ * the response could be:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
@@ -102,12 +96,17 @@
  * <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:
+ * <p>If the service has multiple {@link Dataset}s for different sections of the activity,
+ * for example, a user section for which there are two datasets followed by an address
+ * section for which there are two datasets for each user user, then it should "partition"
+ * the activity in sections and populate the response with just a subset of the data that would
+ * fulfill the first section (the name in our example); then once the user fills the first
+ * section and taps a field from the next section (the address in our example), the Android
+ * system would issue another request for that section, and so on. Note that if the user
+ * chooses to populate the first section with a service provided dataset, the subsequent request
+ * would contain the populated values so you don't try to provide suggestions for the first
+ * section but ony for the second one based on the context of what was already filled. For
+ * example, the first response could be:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
@@ -132,236 +131,182 @@
  *          .setTextFieldValue(id4, "Springfield")
  *          .build())
  *      .add(new Dataset.Builder("Work")
- *          .setTextFieldValue(id3, "Springfield Nuclear Power Plant")
+ *          .setTextFieldValue(id3, "Springfield Power Plant")
  *          .setTextFieldValue(id4, "Springfield")
  *          .build())
  *      .build();
  * </pre>
  *
- * <p>The service could require user authentication, either at the {@link FillResponse} or {@link
- * Dataset} levels, prior to auto-filling the activity - see {@link
- * FillResponse.Builder#requiresFingerprintAuthentication(CryptoObject, Bundle, int)}, {@link
- * FillResponse.Builder#requiresCustomAuthentication(Bundle, int)}, {@link
- * Dataset.Builder#requiresFingerprintAuthentication(CryptoObject, Bundle, int)}, and {@link
- * Dataset.Builder#requiresCustomAuthentication(Bundle, int)} for details.
+ * <p>The service could require user authentication at the {@link FillResponse} or the
+ * {@link Dataset} level, prior to auto-filling an activity - see {@link FillResponse.Builder
+ * #setAuthentication(IntentSender)} and {@link Dataset.Builder#setAuthentication(IntentSender)}.
+ * It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
+ * which would allow you to provide the dataset names to the user and if they choose one
+ * them challenge the user to authenticate. For example, if the user has a home and a work
+ * address the Home and Work labels could be stored unencrypted as they don't have any sensitive
+ * data while the address data is in an encrypted storage. If the user chooses Home, then the
+ * platform will start your authentication flow. If you encrypt all data and require auth
+ * at the response level the user will have to interact with the fill UI to trigger a request
+ * for the datasets as they don't see Home and Work options which will trigger your auth
+ * flow and after successfully authenticating the user will be presented with the Home and
+ * Work options where they can pick one. Hence, you have flexibility how to implement your
+ * auth while storing labels non-encrypted and data encrypted provides a better user
+ * experience.</p>
  *
- * <p>Finally, the service can use the {@link FillResponse.Builder#setExtras(Bundle)} and/or {@link
- * Dataset.Builder#setExtras(Bundle)} methods to pass {@link Bundle}s with service-specific data use
- * to identify this response on future calls (like {@link
- * android.service.autofill.AutoFillService#onSaveRequest(android.app.assist.AssistStructure,
- * Bundle, android.service.autofill.SaveCallback)}) - such bundles will be available as the
- * {@link android.service.autofill.AutoFillService#EXTRA_RESPONSE_EXTRAS} and
- * {@link android.service.autofill.AutoFillService#EXTRA_DATASET_EXTRAS} extras in that method's
- * {@code extras} argument.
+ * <p>Finally, the service can use {@link Dataset.Builder#setExtras(Bundle)} methods
+ * to pass {@link Bundle extras} provided to all future calls related to a dataset,
+ * for example during authentication and saving.</p>
  */
 public final class FillResponse implements Parcelable {
-
-    private final List<Dataset> mDatasets;
-    private final AutoFillId[] mSavableIds;
+    private final String mId;
+    private final ArraySet<Dataset> mDatasets;
+    private final ArraySet<AutoFillId> mSavableIds;
     private final Bundle mExtras;
-    private final int mFlags;
-    private final boolean mRequiresAuth;
-    private final boolean mHasCryptoObject;
-    private final long mCryptoOpId;
+    private final IntentSender mAuthentication;
 
-    private FillResponse(Builder builder) {
-        // TODO(b/33197203): make it immutable?
+    private FillResponse(@NonNull Builder builder) {
+        mId = builder.mId;
         mDatasets = builder.mDatasets;
-        final int size = builder.mSavableIds.size();
-        mSavableIds = new AutoFillId[size];
-        int i = 0;
-        for (AutoFillId id : builder.mSavableIds) {
-            mSavableIds[i++] = id;
-        }
+        mSavableIds = builder.mSavableIds;
         mExtras = builder.mExtras;
-        mFlags = builder.mFlags;
-        mRequiresAuth = builder.mRequiresAuth;
-        mHasCryptoObject = builder.mHasCryptoObject;
-        mCryptoOpId = builder.mCryptoOpId;
+        mAuthentication = builder.mAuthentication;
     }
 
     /** @hide */
-    public List<Dataset> getDatasets() {
-        return mDatasets;
+    public @NonNull String getId() {
+        return mId;
     }
 
     /** @hide */
-    public AutoFillId[] getSavableIds() {
-        return mSavableIds;
-    }
-
-    /** @hide */
-    public Bundle getExtras() {
+    public @Nullable Bundle getExtras() {
         return mExtras;
     }
 
     /** @hide */
-    public int getFlags() {
-        return mFlags;
+    public @Nullable ArraySet<Dataset> getDatasets() {
+        return mDatasets;
     }
 
     /** @hide */
-    public boolean isAuthRequired() {
-        return mRequiresAuth;
+    public @Nullable ArraySet<AutoFillId> getSavableIds() {
+        return mSavableIds;
     }
 
     /** @hide */
-    public boolean hasCryptoObject() {
-        return mHasCryptoObject;
-    }
-
-    /** @hide */
-    public long getCryptoObjectOpId() {
-        return mCryptoOpId;
+    public @Nullable IntentSender getAuthentication() {
+        return mAuthentication;
     }
 
     /**
-     * Builder for {@link FillResponse} objects.
+     * Builder for {@link FillResponse} objects. You must to provide at least
+     * one dataset or set an authentication intent.
      */
     public static final class Builder {
-        private final List<Dataset> mDatasets = new ArrayList<>();
-        private final Set<AutoFillId> mSavableIds = new HashSet<>();
+        private final String mId;
+        private ArraySet<Dataset> mDatasets;
+        private ArraySet<AutoFillId> mSavableIds;
         private Bundle mExtras;
-        private int mFlags;
-        private boolean mRequiresAuth;
-        private boolean mHasCryptoObject;
-        private long mCryptoOpId;
+        private IntentSender mAuthentication;
+        private boolean mDestroyed;
 
-        /**
-         * Requires user authentication through the {@link android.service.autofill.AutoFillService}
-         * before handling an auto-fill request.
-         *
-         * <p>This method is typically called when the device (or the service) does not support
-         * fingerprint authentication (and hence it cannot use {@link
-         * #requiresFingerprintAuthentication(CryptoObject, Bundle, int)}) or when the service needs
-         * to use a custom authentication UI and is used in 2 scenarios:
-         *
-         * <ol>
-         *   <li>When the user data is encrypted and the service must authenticate an object that
-         *       will be used to decrypt it.
-         *   <li>When the service already acquired the user data but wants to confirm the user's
-         *       identity before the activity is filled with it.
-         * </ol>
-         *
-         * <p>When this method is called, the Android System displays an UI affordance asking the
-         * user to tap it to auto-fill the activity; if the user taps it, the Android System calls
-         * {@link
-         * android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
-         * int)} passing {@link
-         * android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_REQUESTED} in the flags and
-         * the same {@code extras} passed to this method. The service can then displays its custom
-         * authentication UI, and then call the proper method on {@link FillCallback} depending on
-         * the authentication result and whether this response already contains the {@link Dataset}s
-         * need to auto-fill the activity:
-         *
-         * <ul>
-         *   <li>If authentication failed, call {@link
-         *       FillCallback#onFillResponseAuthentication(int)} passing {@link
-         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} in the flags.
-         *   <li>If authentication succeeded and this response is empty (no datasets), call {@link
-         *       FillCallback#onSuccess(FillResponse)} with a new dataset (that does not require
-         *       authentication).
-         *   <li>If authentication succeeded and this response is not empty, call {@link
-         *       FillCallback#onFillResponseAuthentication(int)} passing {@link
-         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS} in the flags.
-         * </ul>
-         *
-         * @param extras when set, will be passed back in the {@link
-         *     android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
-         *     int)} call so it could be used by the service to handle state.
-         * @param flags optional parameters, currently ignored.
-         */
-        public Builder requiresCustomAuthentication(@Nullable Bundle extras, int flags) {
-            return requiresAuthentication(null, extras, flags);
+        /** @hide */
+        // TODO(b/33197203): Remove once GCore migrates
+        public Builder() {
+            this(String.valueOf(System.currentTimeMillis()));
         }
 
         /**
-         * Requires user authentication through the Fingerprint sensor before handling an auto-fill
-         * request.
+         * Creates a new {@link FillResponse} builder.
          *
-         * <p>The {@link android.service.autofill.AutoFillService} typically uses this method in 2
-         * situations:
-         *
-         * <ol>
-         *   <li>When the user data is encrypted and the service must authenticate an object that
-         *       will be used to decrypt it.
-         *   <li>When the service already acquired the user data but wants to confirm the user's
-         *       identity before the activity is filled with it.
-         * </ol>
-         *
-         * <p>When this method is called, the Android System displays an UI affordance asking the
-         * user to use the fingerprint sensor to auto-fill the activity, and what happens after a
-         * successful fingerprint authentication depends on the number of {@link Dataset}s included
-         * in this response:
-         *
-         * <ul>
-         *   <li>If it's empty (scenario #1 above), the Android System will call {@link
-         *     android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
-         *       int)} passing {@link
-         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}} in the
-         *       flags.
-         *   <li>If it contains one dataset, the activity will be auto-filled right away.
-         *   <li>If it contains many datasets, the Android System will show dataset picker UI, and
-         *       then auto-fill the activity once the user select the proper datased.
-         * </ul>
-         *
-         * <p>If the fingerprint authentication fails, the Android System will call {@link
-         * android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
-         * int)} passing {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR}
-         * in the flags.
-         *
-         * <p><strong>NOTE: </note> the {@link android.service.autofill.AutoFillService} should use
-         * the {@link android.hardware.fingerprint.FingerprintManager} to check if fingerpint
-         * authentication is available before using this method, and use other alternatives (such as
-         * {@link #requiresCustomAuthentication(Bundle, int)}) if it is not: if this method is
-         * called when fingerprint is not available, Android System will call {@link
-         * android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
-         * int)} passing {@link
-         * android.service.autofill.AutoFillService#FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}
-         * in the flags, but it would be wasting system resources (and worsening the user
-         * experience) in the process.
-         *
-         * @param crypto object that will be authenticated.
-         * @param extras when set, will be passed back in the {@link
-         *     android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
-         *     int)} call so it could be used by the service to handle state.
-         * @param flags optional parameters, currently ignored.
+         * @param id A required id to identify this dataset for future interactions related to it.
          */
-        public Builder requiresFingerprintAuthentication(CryptoObject crypto,
-                @Nullable Bundle extras, int flags) {
-            // TODO(b/33197203): should we allow crypto to be null?
-            Preconditions.checkArgument(crypto != null, "must pass a CryptoObject");
-            return requiresAuthentication(crypto, extras, flags);
+        public Builder(@NonNull String id) {
+            mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty or null");
         }
 
-        private Builder requiresAuthentication(CryptoObject cryptoObject, Bundle extras,
-                int flags) {
-            // There can be only one!
-            Preconditions.checkState(!mRequiresAuth,
-                    "requires-authentication methods already called");
-            // TODO(b/33197203): make sure that either this method or setExtras() is called, but
-            // not both
-            mExtras = extras;
-            mFlags = flags;
-            mRequiresAuth = true;
-            if (cryptoObject != null) {
-                mHasCryptoObject = true;
-                mCryptoOpId = cryptoObject.getOpId();
-            }
+        /**
+         * Requires a fill response authentication before auto-filling the activity with
+         * any dataset in this response. This is typically useful when a user interaction
+         * is required to unlock their data vault if you encrypt the dataset labels and
+         * dataset data. It is recommended to encrypt only the sensitive data and not the
+         * dataset labels which would allow auth on the dataset level leading to a better
+         * user experience. Note that if you use sensitive data as a label, for example an
+         * email address, then it should also be encrypted.
+         *
+         * <p>This method is called when you need to provide an authentication
+         * UI for the fill response. For example, when the user's data is stored
+         * encrypted and needs a user interaction to decrypt before offering fill
+         * suggestions.</p>
+         *
+         * <p>When a user initiates an auto fill, the system triggers the provided
+         * intent whose extras will have the {@link android.content.Intent
+         * #EXTRA_AUTO_FILL_ITEM_ID id} of the {@link android.view.autofill.FillResponse})
+         * to authenticate, the {@link android.content.Intent#EXTRA_AUTO_FILL_EXTRAS extras}
+         * associated with this response, and a {@link android.content.Intent
+         * #EXTRA_AUTO_FILL_CALLBACK callback} to dispatch the authentication result.</p>
+         *
+         * <p>Once you complete your authentication flow you should use the provided callback
+         * to notify for a failure or a success. In case of a success you need to provide
+         * the fully populated response that is being authenticated. For example, if you
+         * provided an empty {@link FillResponse} because the user's data was locked and
+         * marked that the response needs an authentication then in the response returned
+         * if authentication succeeds you need to provide all available datasets some of
+         * which may need to be further authenticated, for example a credit card whose
+         * CVV needs to be entered.</p>
+         *
+         * <p>The indent sender mechanism allows you to have your authentication UI
+         * implemented as an activity or a service or a receiver. However, the recommended
+         * way is to do this is with an activity which the system will start in the
+         * filled activity's task meaning it will properly work with back, recent apps, and
+         * free-form multi-window, while avoiding the need for the "draw on top of other"
+         * apps special permission. You can still theme your authentication activity's
+         * UI to look like a dialog if desired.</p>
+         *
+         * <p></><strong>Note:</strong> Do not make the provided intent sender
+         * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
+         * platform needs to fill in the authentication arguments.</p>
+         *
+         * @param authentication Intent to trigger your authentication flow.
+         *
+         * @see android.app.PendingIntent#getIntentSender()
+         */
+        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) {
+            throwIfDestroyed();
+            mAuthentication = authentication;
             return this;
         }
 
         /**
-         * Adds a new {@link Dataset} to this response.
+         * Adds a new {@link Dataset} to this response. Adding a dataset with the
+         * same id updates the existing one.
          *
          * @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
-            mDatasets.add(dataset);
-            for (DatasetField field : dataset.getFields()) {
-                mSavableIds.add(field.getId());
+        public@NonNull Builder addDataset(@Nullable Dataset dataset) {
+            throwIfDestroyed();
+            if (dataset == null) {
+                return this;
+            }
+            if (mDatasets == null) {
+                mDatasets = new ArraySet<>();
+            }
+            final int datasetCount = mDatasets.size();
+            for (int i = 0; i < datasetCount; i++) {
+                if (mDatasets.valueAt(i).getName().equals(dataset.getName())) {
+                    throw new IllegalArgumentException("Duplicate dataset name: "
+                            + dataset.getName());
+                }
+            }
+            if (!mDatasets.add(dataset)) {
+                return this;
+            }
+            final int fieldCount = dataset.getFieldIds().size();
+            for (int i = 0; i < fieldCount; i++) {
+                final AutoFillId id = dataset.getFieldIds().get(i);
+                if (mSavableIds == null) {
+                    mSavableIds = new ArraySet<>();
+                }
+                mSavableIds.add(id);
             }
             return this;
         }
@@ -374,27 +319,35 @@
          *
          * <p>See {@link FillResponse} for examples.
          */
-        public Builder addSavableFields(AutoFillId... ids) {
+        public @NonNull Builder addSavableFields(@Nullable AutoFillId... ids) {
+            throwIfDestroyed();
+            if (ids == null) {
+                return this;
+            }
             for (AutoFillId id : ids) {
+                if (mSavableIds == null) {
+                    mSavableIds = new ArraySet<>();
+                }
                 mSavableIds.add(id);
             }
             return this;
         }
 
         /**
-         * Sets a {@link Bundle} that will be passed to subsequent calls to {@link
-         * android.service.autofill.AutoFillService} methods such as {@link
+         * Sets a {@link Bundle} that will be passed to subsequent APIs that
+         * manipulate this response. For example, they are passed in as {@link
+         * android.content.Intent#EXTRA_AUTO_FILL_EXTRAS extras} to your
+         * authentication flow and to subsequent calls to {@link
+         * android.service.autofill.AutoFillService#onFillRequest(
+         * android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal,
+         * android.service.autofill.FillCallback)} and {@link
          * android.service.autofill.AutoFillService#onSaveRequest(
-         * android.app.assist.AssistStructure, Bundle, android.service.autofill.SaveCallback)},
-         * using {@link
-         * android.service.autofill.AutoFillService#EXTRA_RESPONSE_EXTRAS} as the key.
-         *
-         * <p>It can be used when to keep service state in between calls.
+         * android.app.assist.AssistStructure, Bundle,
+         * android.service.autofill.SaveCallback)}.
          */
         public Builder setExtras(Bundle extras) {
-            // TODO(b/33197203): make sure that either this method or the requires-Authentication
-            // ones are called, but not both
-            mExtras = Objects.requireNonNull(extras, "extras cannot be null");
+            throwIfDestroyed();
+            mExtras = extras;
             return this;
         }
 
@@ -402,8 +355,16 @@
          * Builds a new {@link FillResponse} instance.
          */
         public FillResponse build() {
+            throwIfDestroyed();
+            mDestroyed = true;
             return new FillResponse(this);
         }
+
+        private void throwIfDestroyed() {
+            if (mDestroyed) {
+                throw new IllegalStateException("Already called #build()");
+            }
+        }
     }
 
     /////////////////////////////////////
@@ -412,14 +373,12 @@
     @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)
-            .append(", flags=").append(mFlags)
-            .append(", requiresAuth: ").append(mRequiresAuth)
-            .append(", hasCrypto: ").append(mHasCryptoObject);
+        final StringBuilder builder = new StringBuilder(
+                "FillResponse: [id=").append(mId)
+                .append(", datasets=").append(mDatasets)
+                .append(", savableIds=").append(mSavableIds)
+                .append(", hasExtras=").append(mExtras != null)
+                .append(", hasAuthentication=").append(mAuthentication != null);
         return builder.append(']').toString();
     }
 
@@ -434,33 +393,34 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeList(mDatasets);
-        parcel.writeParcelableArray(mSavableIds, 0);
-        parcel.writeBundle(mExtras);
-        parcel.writeInt(mFlags);
-        parcel.writeInt(mRequiresAuth ? 1 : 0);
-        parcel.writeInt(mHasCryptoObject ? 1 : 0);
-        if (mHasCryptoObject) {
-            parcel.writeLong(mCryptoOpId);
-        }
-    }
-
-    private FillResponse(Parcel parcel) {
-        mDatasets = new ArrayList<>();
-        parcel.readList(mDatasets, null);
-        mSavableIds = parcel.readParcelableArray(null, AutoFillId.class);
-        mExtras = parcel.readBundle();
-        mFlags = parcel.readInt();
-        mRequiresAuth = parcel.readInt() == 1;
-        mHasCryptoObject = parcel.readInt() == 1;
-        mCryptoOpId = mHasCryptoObject ? parcel.readLong() : 0;
+        parcel.writeString(mId);
+        parcel.writeTypedArraySet(mDatasets, 0);
+        parcel.writeTypedArraySet(mSavableIds, 0);
+        parcel.writeParcelable(mExtras, 0);
+        parcel.writeParcelable(mAuthentication, 0);
     }
 
     public static final Parcelable.Creator<FillResponse> CREATOR =
             new Parcelable.Creator<FillResponse>() {
         @Override
-        public FillResponse createFromParcel(Parcel source) {
-            return new FillResponse(source);
+        public FillResponse createFromParcel(Parcel parcel) {
+            // Always go through the builder to ensure the data ingested by
+            // the system obeys the contract of the builder to avoid attacks
+            // using specially crafted parcels.
+            final Builder builder = new Builder(parcel.readString());
+            final ArraySet<Dataset> datasets = parcel.readTypedArraySet(null);
+            final int datasetCount = (datasets != null) ? datasets.size() : 0;
+            for (int i = 0; i < datasetCount; i++) {
+                builder.addDataset(datasets.valueAt(i));
+            }
+            final ArraySet<AutoFillId> fillIds = parcel.readTypedArraySet(null);
+            final int fillIdCount = (fillIds != null) ? fillIds.size() : 0;
+            for (int i = 0; i < fillIdCount; i++) {
+                builder.addSavableFields(fillIds.valueAt(i));
+            }
+            builder.setExtras(parcel.readParcelable(null));
+            builder.setAuthentication(parcel.readParcelable(null));
+            return builder.build();
         }
 
         @Override
diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java
index 14cf9e8..a9844d7 100644
--- a/core/java/android/view/autofill/Helper.java
+++ b/core/java/android/view/autofill/Helper.java
@@ -26,6 +26,7 @@
 public final class Helper {
 
     static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable
+    static final boolean VERBOSE = false;
     static final String REDACTED = "[REDACTED]";
 
     static StringBuilder append(StringBuilder builder, Bundle bundle) {
diff --git a/core/java/android/view/autofill/VirtualViewDelegate.java b/core/java/android/view/autofill/VirtualViewDelegate.java
index e465c67..3dda7f7 100644
--- a/core/java/android/view/autofill/VirtualViewDelegate.java
+++ b/core/java/android/view/autofill/VirtualViewDelegate.java
@@ -15,9 +15,6 @@
  */
 package android.view.autofill;
 
-import android.annotation.Nullable;
-import android.graphics.Rect;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewStructure;
 
@@ -33,7 +30,7 @@
  * class.
  *
  * <p>Objects of this class are typically created by overriding
- * {@link View#getAutoFillVirtualViewDelegate(Callback)} and saving the passed callback, which must
+ * {@link View#getAutoFillVirtualViewDelegate()} 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
@@ -43,82 +40,22 @@
  *   <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}.
+ * virtual child 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.
+ *   <li>This provider than finds the child 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 virtualId id identifying the virtual child 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 auto-fill bar for a child must be updated.
-         *
-         * See {@link AutoFillManager#updateAutoFillInput(View, int, android.graphics.Rect, int)}
-         * for more details.
-         */
-        // TODO(b/33197203): do we really need it, or should the parent view just call
-        // AutoFillManager.updateAutoFillInput() directly?
-        public void onAutoFillInputUpdated(int virtualId, @Nullable Rect boundaries, int flags) {
-            if (DEBUG) {
-                Log.v(TAG, "onAutoFillInputUpdated(): virtualId=" + virtualId + ", boundaries="
-                        + boundaries + ", flags=" + flags);
-            }
-        }
-
-        /**
-         * 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/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 9a39a17..51587a7 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -250,7 +250,7 @@
         mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
         mDefaultActivityButton.setOnClickListener(mCallbacks);
         mDefaultActivityButton.setOnLongClickListener(mCallbacks);
-        mDefaultActivityButtonImage = mDefaultActivityButton.findViewById(R.id.image);
+        mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
 
         final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
         expandButton.setOnClickListener(mCallbacks);
@@ -282,7 +282,7 @@
         mExpandActivityOverflowButton = expandButton;
 
         mExpandActivityOverflowButtonImage =
-            expandButton.findViewById(R.id.image);
+            (ImageView) expandButton.findViewById(R.id.image);
         mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
 
         mAdapter = new ActivityChooserViewAdapter();
@@ -760,7 +760,7 @@
                         convertView = LayoutInflater.from(getContext()).inflate(
                                 R.layout.activity_chooser_view_list_item, parent, false);
                         convertView.setId(ITEM_VIEW_TYPE_FOOTER);
-                        TextView titleView = convertView.findViewById(R.id.title);
+                        TextView titleView = (TextView) convertView.findViewById(R.id.title);
                         titleView.setText(mContext.getString(
                                 R.string.activity_chooser_view_see_all));
                     }
@@ -772,11 +772,11 @@
                     }
                     PackageManager packageManager = mContext.getPackageManager();
                     // Set the icon
-                    ImageView iconView = convertView.findViewById(R.id.icon);
+                    ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
                     ResolveInfo activity = (ResolveInfo) getItem(position);
                     iconView.setImageDrawable(activity.loadIcon(packageManager));
                     // Set the title.
-                    TextView titleView = convertView.findViewById(R.id.title);
+                    TextView titleView = (TextView) convertView.findViewById(R.id.title);
                     titleView.setText(activity.loadLabel(packageManager));
                     // Highlight the default.
                     if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 06d4868..68e6809 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -451,7 +451,7 @@
 
     private View getPermissionsView(int which, boolean showRevokeUI) {
         LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
-        LinearLayout displayList = permsView.findViewById(R.id.perms_list);
+        LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
         View noPermsView = permsView.findViewById(R.id.no_permissions);
 
         displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
@@ -517,8 +517,8 @@
             CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
         View permView = inflater.inflate(R.layout.app_permission_item_old, null);
 
-        TextView permGrpView = permView.findViewById(R.id.permission_group);
-        TextView permDescView = permView.findViewById(R.id.permission_list);
+        TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
+        TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
 
         ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
         imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 81f0d3d..bbc50da 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -388,7 +388,7 @@
                 text = (TextView) view;
             } else {
                 //  Otherwise, find the TextView field within the layout
-                text = view.findViewById(mFieldId);
+                text = (TextView) view.findViewById(mFieldId);
 
                 if (text == null) {
                     throw new RuntimeException("Failed to find view with ID "
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 1b899db..557d411 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -316,9 +316,9 @@
         View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
         mDelegator.addView(content);
 
-        mListView = mDelegator.findViewById(R.id.list);
-        mDayNamesHeader = content.findViewById(R.id.day_names);
-        mMonthName = content.findViewById(R.id.month_name);
+        mListView = (ListView) mDelegator.findViewById(R.id.list);
+        mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
+        mMonthName = (TextView) content.findViewById(R.id.month_name);
 
         setUpHeader();
         setUpListView();
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 500f381..6f687fe 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -32,7 +32,6 @@
 import android.view.SoundEffectConstants;
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
-import android.view.ViewStructure;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.autofill.AutoFillType;
@@ -562,17 +561,14 @@
         stream.addProperty("checked", isChecked());
     }
 
-    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
 
-    @Override
-    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutoFillStructure(structure, flags);
-        structure.setAutoFillValue(AutoFillValue.forToggle(isChecked()));
-        // TODO(b/33197203): add unit/CTS tests for auto-fill methods
-    }
+    // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener
 
     @Override
     public void autoFill(AutoFillValue value) {
+        if (!isEnabled()) return;
+
         setChecked(value.getToggleValue());
     }
 
@@ -580,4 +576,9 @@
     public AutoFillType getAutoFillType() {
         return AutoFillType.forToggle();
     }
+
+    @Override
+    public AutoFillValue getAutoFillValue() {
+        return isEnabled() ? null : AutoFillValue.forToggle(isChecked());
+    }
 }
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 907250a..f712685 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,10 +115,10 @@
         mDelegator.addView(mContainer);
 
         // Set up header views.
-        final ViewGroup header = mContainer.findViewById(R.id.date_picker_header);
-        mHeaderYear = header.findViewById(R.id.date_picker_header_year);
+        final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
+        mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
         mHeaderYear.setOnClickListener(mOnHeaderClickListener);
-        mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date);
+        mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
         mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
 
         // For the sake of backwards compatibility, attempt to extract the text
@@ -154,10 +154,10 @@
         a.recycle();
 
         // Set up picker container.
-        mAnimator = mContainer.findViewById(R.id.animator);
+        mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
 
         // Set up day picker view.
-        mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker);
+        mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
         mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
         mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
         mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
@@ -165,7 +165,7 @@
         mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
 
         // Set up year picker view.
-        mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker);
+        mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
         mYearPickerView.setRange(mMinDate, mMaxDate);
         mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
         mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 63621e1..8d5bf8f 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -225,7 +225,7 @@
     public Object instantiateItem(ViewGroup container, int position) {
         final View itemView = mInflater.inflate(mLayoutResId, container, false);
 
-        final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
+        final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
         v.setOnDayClickListener(mOnDayClickListener);
         v.setMonthTextAppearance(mMonthTextAppearance);
         v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index 058baa6..94022ae 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -137,10 +137,9 @@
     }
 
     @Override
-    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
-            View childToSkip) {
+    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
         if (predicate.apply(this)) {
-            return (T) this;
+            return this;
         }
 
         // Always try the selected view first.
@@ -149,7 +148,7 @@
         if (current != childToSkip && current != null) {
             final View v = current.findViewByPredicate(predicate);
             if (v != null) {
-                return (T) v;
+                return v;
             }
         }
 
@@ -161,7 +160,7 @@
                 final View v = child.findViewByPredicate(predicate);
 
                 if (v != null) {
-                    return (T) v;
+                    return v;
                 }
             }
         }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index a2cb491..76ed80f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -95,7 +95,6 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
-import android.view.ViewParent;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -140,7 +139,6 @@
     private static final boolean DEBUG_UNDO = false;
 
     static final int BLINK = 500;
-    private static final float[] TEMP_POSITION = new float[2];
     private static final int DRAG_SHADOW_MAX_TEXT_LENGTH = 20;
     private static final float LINE_SLOP_MULTIPLIER_FOR_HANDLEVIEWS = 0.5f;
     private static final int UNSET_X_VALUE = -1;
@@ -1032,46 +1030,6 @@
                 boolean parentPositionChanged, boolean parentScrolled);
     }
 
-    private boolean isPositionVisible(final float positionX, final float positionY) {
-        synchronized (TEMP_POSITION) {
-            final float[] position = TEMP_POSITION;
-            position[0] = positionX;
-            position[1] = positionY;
-            View view = mTextView;
-
-            while (view != null) {
-                if (view != mTextView) {
-                    // Local scroll is already taken into account in positionX/Y
-                    position[0] -= view.getScrollX();
-                    position[1] -= view.getScrollY();
-                }
-
-                if (position[0] < 0 || position[1] < 0 || position[0] > view.getWidth()
-                        || position[1] > view.getHeight()) {
-                    return false;
-                }
-
-                if (!view.getMatrix().isIdentity()) {
-                    view.getMatrix().mapPoints(position);
-                }
-
-                position[0] += view.getLeft();
-                position[1] += view.getTop();
-
-                final ViewParent parent = view.getParent();
-                if (parent instanceof View) {
-                    view = (View) parent;
-                } else {
-                    // We've reached the ViewRoot, stop iterating
-                    view = null;
-                }
-            }
-        }
-
-        // We've been able to walk up the view hierarchy and the position was never clipped
-        return true;
-    }
-
     private boolean isOffsetVisible(int offset) {
         Layout layout = mTextView.getLayout();
         if (layout == null) return false;
@@ -1079,7 +1037,8 @@
         final int line = layout.getLineForOffset(offset);
         final int lineBottom = layout.getLineBottom(line);
         final int primaryHorizontal = (int) layout.getPrimaryHorizontal(offset);
-        return isPositionVisible(primaryHorizontal + mTextView.viewportToContentHorizontalOffset(),
+        return mTextView.isPositionVisible(
+                primaryHorizontal + mTextView.viewportToContentHorizontalOffset(),
                 lineBottom + mTextView.viewportToContentVerticalOffset());
     }
 
@@ -4099,69 +4058,9 @@
                     final CharSequence composingText = text.subSequence(composingTextStart,
                             composingTextEnd);
                     builder.setComposingText(composingTextStart, composingText);
-
-                    final int minLine = layout.getLineForOffset(composingTextStart);
-                    final int maxLine = layout.getLineForOffset(composingTextEnd - 1);
-                    for (int line = minLine; line <= maxLine; ++line) {
-                        final int lineStart = layout.getLineStart(line);
-                        final int lineEnd = layout.getLineEnd(line);
-                        final int offsetStart = Math.max(lineStart, composingTextStart);
-                        final int offsetEnd = Math.min(lineEnd, composingTextEnd);
-                        final boolean ltrLine =
-                                layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
-                        final float[] widths = new float[offsetEnd - offsetStart];
-                        layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths);
-                        final float top = layout.getLineTop(line);
-                        final float bottom = layout.getLineBottom(line);
-                        for (int offset = offsetStart; offset < offsetEnd; ++offset) {
-                            final float charWidth = widths[offset - offsetStart];
-                            final boolean isRtl = layout.isRtlCharAt(offset);
-                            final float primary = layout.getPrimaryHorizontal(offset);
-                            final float secondary = layout.getSecondaryHorizontal(offset);
-                            // TODO: This doesn't work perfectly for text with custom styles and
-                            // TAB chars.
-                            final float left;
-                            final float right;
-                            if (ltrLine) {
-                                if (isRtl) {
-                                    left = secondary - charWidth;
-                                    right = secondary;
-                                } else {
-                                    left = primary;
-                                    right = primary + charWidth;
-                                }
-                            } else {
-                                if (!isRtl) {
-                                    left = secondary;
-                                    right = secondary + charWidth;
-                                } else {
-                                    left = primary - charWidth;
-                                    right = primary;
-                                }
-                            }
-                            // TODO: Check top-right and bottom-left as well.
-                            final float localLeft = left + viewportToContentHorizontalOffset;
-                            final float localRight = right + viewportToContentHorizontalOffset;
-                            final float localTop = top + viewportToContentVerticalOffset;
-                            final float localBottom = bottom + viewportToContentVerticalOffset;
-                            final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop);
-                            final boolean isBottomRightVisible =
-                                    isPositionVisible(localRight, localBottom);
-                            int characterBoundsFlags = 0;
-                            if (isTopLeftVisible || isBottomRightVisible) {
-                                characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
-                            }
-                            if (!isTopLeftVisible || !isBottomRightVisible) {
-                                characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
-                            }
-                            if (isRtl) {
-                                characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
-                            }
-                            // Here offset is the index in Java chars.
-                            builder.addCharacterBounds(offset, localLeft, localTop, localRight,
-                                    localBottom, characterBoundsFlags);
-                        }
-                    }
+                    mTextView.populateCharacterBounds(builder, composingTextStart,
+                            composingTextEnd, viewportToContentHorizontalOffset,
+                            viewportToContentVerticalOffset);
                 }
             }
 
@@ -4177,10 +4076,10 @@
                         + viewportToContentVerticalOffset;
                 final float insertionMarkerBottom = layout.getLineBottom(line)
                         + viewportToContentVerticalOffset;
-                final boolean isTopVisible =
-                        isPositionVisible(insertionMarkerX, insertionMarkerTop);
-                final boolean isBottomVisible =
-                        isPositionVisible(insertionMarkerX, insertionMarkerBottom);
+                final boolean isTopVisible = mTextView
+                        .isPositionVisible(insertionMarkerX, insertionMarkerTop);
+                final boolean isBottomVisible = mTextView
+                        .isPositionVisible(insertionMarkerX, insertionMarkerBottom);
                 int insertionMarkerFlags = 0;
                 if (isTopVisible || isBottomVisible) {
                     insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
@@ -4388,7 +4287,8 @@
                 return false;
             }
 
-            return isPositionVisible(mPositionX + mHotspotX + getHorizontalOffset(), mPositionY);
+            return mTextView.isPositionVisible(
+                    mPositionX + mHotspotX + getHorizontalOffset(), mPositionY);
         }
 
         public abstract int getCurrentCursorOffset();
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index b7da04e..80780a6 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3740,21 +3740,20 @@
      * @removed For internal use only. This should have been hidden.
      */
     @Override
-    protected <T extends View> T findViewTraversal(@IdRes int id) {
-        // First look in our children, then in any header and footer views that
-        // may be scrolled off.
-        View v = super.findViewTraversal(id);
+    protected View findViewTraversal(@IdRes int id) {
+        View v;
+        v = super.findViewTraversal(id);
         if (v == null) {
             v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
             if (v != null) {
-                return (T) v;
+                return v;
             }
             v = findViewInHeadersOrFooters(mFooterViewInfos, id);
             if (v != null) {
-                return (T) v;
+                return v;
             }
         }
-        return (T) v;
+        return v;
     }
 
     View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
@@ -3783,22 +3782,21 @@
      * @removed For internal use only. This should have been hidden.
      */
     @Override
-    protected <T extends View> T findViewWithTagTraversal(Object tag) {
-        // First look in our children, then in any header and footer views that
-        // may be scrolled off.
-        View v = super.findViewWithTagTraversal(tag);
+    protected View findViewWithTagTraversal(Object tag) {
+        View v;
+        v = super.findViewWithTagTraversal(tag);
         if (v == null) {
             v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
             if (v != null) {
-                return (T) v;
+                return v;
             }
 
             v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
             if (v != null) {
-                return (T) v;
+                return v;
             }
         }
-        return (T) v;
+        return v;
     }
 
     View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
@@ -3831,21 +3829,21 @@
      * @hide
      */
     @Override
-    protected <T extends View> T findViewByPredicateTraversal(
-            Predicate<View> predicate, View childToSkip) {
-        View v = super.findViewByPredicateTraversal(predicate, childToSkip);
+    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+        View v;
+        v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null) {
             v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
             if (v != null) {
-                return (T) v;
+                return v;
             }
 
             v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
             if (v != null) {
-                return (T) v;
+                return v;
             }
         }
-        return (T) v;
+        return v;
     }
 
     /**
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8e04f1c..8008637 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -257,13 +257,13 @@
                 .getText(com.android.internal.R.string.lockscreen_transport_play_description);
         mPauseDescription = res
                 .getText(com.android.internal.R.string.lockscreen_transport_pause_description);
-        mPauseButton = v.findViewById(com.android.internal.R.id.pause);
+        mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
         if (mPauseButton != null) {
             mPauseButton.requestFocus();
             mPauseButton.setOnClickListener(mPauseListener);
         }
 
-        mFfwdButton = v.findViewById(com.android.internal.R.id.ffwd);
+        mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
         if (mFfwdButton != null) {
             mFfwdButton.setOnClickListener(mFfwdListener);
             if (!mFromXml) {
@@ -271,7 +271,7 @@
             }
         }
 
-        mRewButton = v.findViewById(com.android.internal.R.id.rew);
+        mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
         if (mRewButton != null) {
             mRewButton.setOnClickListener(mRewListener);
             if (!mFromXml) {
@@ -280,16 +280,16 @@
         }
 
         // By default these are hidden. They will be enabled when setPrevNextListeners() is called
-        mNextButton = v.findViewById(com.android.internal.R.id.next);
+        mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
         if (mNextButton != null && !mFromXml && !mListenersSet) {
             mNextButton.setVisibility(View.GONE);
         }
-        mPrevButton = v.findViewById(com.android.internal.R.id.prev);
+        mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
         if (mPrevButton != null && !mFromXml && !mListenersSet) {
             mPrevButton.setVisibility(View.GONE);
         }
 
-        mProgress = v.findViewById(com.android.internal.R.id.mediacontroller_progress);
+        mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
         if (mProgress != null) {
             if (mProgress instanceof SeekBar) {
                 SeekBar seeker = (SeekBar) mProgress;
@@ -298,8 +298,8 @@
             mProgress.setMax(1000);
         }
 
-        mEndTime = v.findViewById(com.android.internal.R.id.time);
-        mCurrentTime = v.findViewById(com.android.internal.R.id.time_current);
+        mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
+        mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
         mFormatBuilder = new StringBuilder();
         mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
 
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 5199b26..989927e 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -35,8 +35,8 @@
 import android.transition.Transition;
 import android.transition.Transition.EpicenterCallback;
 import android.transition.Transition.TransitionListener;
-import android.transition.Transition.TransitionListenerAdapter;
 import android.transition.TransitionInflater;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.transition.TransitionSet;
 import android.util.AttributeSet;
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 72dc1cc..8ba4694 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -24,7 +24,6 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewStructure;
 import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 
@@ -404,16 +403,14 @@
         }
     }
 
-    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods (and make sure they handle enable)
 
-    @Override
-    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutoFillStructure(structure, flags);
-        structure.setAutoFillValue(AutoFillValue.forList(getCheckedRadioButtonId()));
-    }
+    // TODO(b/33197203): override onProvideAutoFillStructure and add a change listener
 
     @Override
     public void autoFill(AutoFillValue value) {
+        if (!isEnabled()) return;
+
         final int index = value.getListValue();
         final View child = getChildAt(index);
         if (child == null) {
@@ -427,4 +424,9 @@
     public AutoFillType getAutoFillType() {
         return AutoFillType.forList();
     }
+
+    @Override
+    public AutoFillValue getAutoFillValue() {
+        return isEnabled() ? AutoFillValue.forList(getCheckedRadioButtonId()) : null;
+    }
 }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5505f2f..359d04e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1578,7 +1578,7 @@
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
             final Context context = root.getContext();
-            final ViewGroup target = root.findViewById(viewId);
+            final ViewGroup target = (ViewGroup) root.findViewById(viewId);
             if (target == null) return;
             if (nestedViews != null) {
                 // Inflate nested views and add as children
@@ -1757,7 +1757,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = root.findViewById(viewId);
+            final TextView target = (TextView) root.findViewById(viewId);
             if (target == null) return;
             if (drawablesLoaded) {
                 if (isRelative) {
@@ -1857,7 +1857,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = root.findViewById(viewId);
+            final TextView target = (TextView) root.findViewById(viewId);
             if (target == null) return;
             target.setTextSize(units, size);
         }
@@ -2045,7 +2045,7 @@
 
         @Override
         public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = root.findViewById(viewId);
+            final TextView target = (TextView) root.findViewById(viewId);
             if (target == null) return;
             Drawable[] drawables = isRelative
                     ? target.getCompoundDrawablesRelative()
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index fbb8993..f833d1b 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -286,7 +286,7 @@
         v.setTag(new ChildViewCache(v));
 
         // Set up icon.
-        final ImageView iconRefine = v.findViewById(R.id.edit_query);
+        final ImageView iconRefine = (ImageView) v.findViewById(R.id.edit_query);
         iconRefine.setImageResource(mCommitIconResId);
 
         return v;
@@ -304,11 +304,11 @@
         public final ImageView mIconRefine;
 
         public ChildViewCache(View v) {
-            mText1 = v.findViewById(com.android.internal.R.id.text1);
-            mText2 = v.findViewById(com.android.internal.R.id.text2);
-            mIcon1 = v.findViewById(com.android.internal.R.id.icon1);
-            mIcon2 = v.findViewById(com.android.internal.R.id.icon2);
-            mIconRefine = v.findViewById(com.android.internal.R.id.edit_query);
+            mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
+            mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
+            mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
+            mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
+            mIconRefine = (ImageView) v.findViewById(com.android.internal.R.id.edit_query);
         }
     }
 
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 7e2cadf..32418cd 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -619,7 +619,7 @@
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
-            final TextView tv = tabIndicator.findViewById(R.id.title);
+            final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
             tv.setText(mLabel);
 
             if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
@@ -653,8 +653,8 @@
                     mTabWidget, // tab widget is the parent
                     false); // no inflate params
 
-            final TextView tv = tabIndicator.findViewById(R.id.title);
-            final ImageView iconView = tabIndicator.findViewById(R.id.icon);
+            final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
+            final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
 
             // when icon is gone by default, we're in exclusive mode
             final boolean exclusive = iconView.getVisibility() == View.GONE;
diff --git a/core/java/android/widget/TextInputTimePickerView.java b/core/java/android/widget/TextInputTimePickerView.java
new file mode 100644
index 0000000..ef91576
--- /dev/null
+++ b/core/java/android/widget/TextInputTimePickerView.java
@@ -0,0 +1,249 @@
+/*
+ * 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 android.content.Context;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.MathUtils;
+import android.view.View;
+
+import com.android.internal.R;
+
+/**
+ * View to show text input based time picker with hour and minute fields and an optional AM/PM
+ * spinner.
+ *
+ * @hide
+ */
+public class TextInputTimePickerView extends RelativeLayout {
+    public static final int HOURS = 0;
+    public static final int MINUTES = 1;
+    public static final int AMPM = 2;
+
+    private static final int AM = 0;
+    private static final int PM = 1;
+
+    private final EditText mHourEditText;
+    private final EditText mMinuteEditText;
+    private final TextView mInputSeparatorView;
+    private final Spinner mAmPmSpinner;
+    private final TextView mErrorLabel;
+    private final TextView mHourLabel;
+    private final TextView mMinuteLabel;
+
+    private boolean mIs24Hour;
+    private boolean mHourFormatStartsAtZero;
+    private OnValueTypedListener mListener;
+
+    private boolean mErrorShowing;
+
+    interface OnValueTypedListener {
+        void onValueChanged(int inputType, int newValue);
+    }
+
+    public TextInputTimePickerView(Context context) {
+        this(context, null);
+    }
+
+    public TextInputTimePickerView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TextInputTimePickerView(Context context, AttributeSet attrs, int defStyle) {
+        this(context, attrs, defStyle, 0);
+    }
+
+    public TextInputTimePickerView(Context context, AttributeSet attrs, int defStyle,
+            int defStyleRes) {
+        super(context, attrs, defStyle, defStyleRes);
+
+        inflate(context, R.layout.time_picker_text_input_material, this);
+
+        mHourEditText = (EditText) findViewById(R.id.input_hour);
+        mMinuteEditText = (EditText) findViewById(R.id.input_minute);
+        mInputSeparatorView = (TextView) findViewById(R.id.input_separator);
+        mErrorLabel = (TextView) findViewById(R.id.label_error);
+        mHourLabel = (TextView) findViewById(R.id.label_hour);
+        mMinuteLabel = (TextView) findViewById(R.id.label_minute);
+
+        mHourEditText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+            @Override
+            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+            @Override
+            public void afterTextChanged(Editable editable) {
+                parseAndSetHourInternal(editable.toString());
+            }
+        });
+
+        mMinuteEditText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+            @Override
+            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
+
+            @Override
+            public void afterTextChanged(Editable editable) {
+                parseAndSetMinuteInternal(editable.toString());
+            }
+        });
+
+        mAmPmSpinner = (Spinner) findViewById(R.id.am_pm_spinner);
+        final String[] amPmStrings = TimePicker.getAmPmStrings(context);
+        ArrayAdapter<CharSequence> adapter =
+                new ArrayAdapter<CharSequence>(context, R.layout.simple_spinner_dropdown_item);
+        adapter.add(TimePickerClockDelegate.obtainVerbatim(amPmStrings[0]));
+        adapter.add(TimePickerClockDelegate.obtainVerbatim(amPmStrings[1]));
+        mAmPmSpinner.setAdapter(adapter);
+        mAmPmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> adapterView, View view, int position,
+                    long id) {
+                if (position == 0) {
+                    mListener.onValueChanged(AMPM, AM);
+                } else {
+                    mListener.onValueChanged(AMPM, PM);
+                }
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> adapterView) {}
+        });
+    }
+
+    void setListener(OnValueTypedListener listener) {
+        mListener = listener;
+    }
+
+    void setHourFormat(int maxCharLength) {
+        mHourEditText.setFilters(new InputFilter[] {
+                new InputFilter.LengthFilter(maxCharLength)});
+        mMinuteEditText.setFilters(new InputFilter[] {
+                new InputFilter.LengthFilter(maxCharLength)});
+    }
+
+    boolean validateInput() {
+        final boolean inputValid = parseAndSetHourInternal(mHourEditText.getText().toString())
+                && parseAndSetMinuteInternal(mMinuteEditText.getText().toString());
+        setError(!inputValid);
+        return inputValid;
+    }
+
+    void updateSeparator(String separatorText) {
+        mInputSeparatorView.setText(separatorText);
+    }
+
+    private void setError(boolean enabled) {
+        mErrorShowing = enabled;
+
+        mErrorLabel.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
+        mHourLabel.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
+        mMinuteLabel.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
+    }
+
+    /**
+     * Computes the display value and updates the text of the view.
+     * <p>
+     * This method should be called whenever the current value or display
+     * properties (leading zeroes, max digits) change.
+     */
+    void updateTextInputValues(int localizedHour, int minute, int amOrPm, boolean is24Hour,
+            boolean hourFormatStartsAtZero) {
+        final String format = "%d";
+
+        mIs24Hour = is24Hour;
+        mHourFormatStartsAtZero = hourFormatStartsAtZero;
+
+        mAmPmSpinner.setVisibility(is24Hour ? View.INVISIBLE : View.VISIBLE);
+
+        mHourEditText.setText(String.format(format, localizedHour));
+        mMinuteEditText.setText(String.format(format, minute));
+
+        if (amOrPm == AM) {
+            mAmPmSpinner.setSelection(0);
+        } else {
+            mAmPmSpinner.setSelection(1);
+        }
+
+        if (mErrorShowing) {
+            validateInput();
+        }
+    }
+
+    private boolean parseAndSetHourInternal(String input) {
+        try {
+            final int hour = Integer.parseInt(input);
+            if (!isValidLocalizedHour(hour)) {
+                final int minHour = mHourFormatStartsAtZero ? 0 : 1;
+                final int maxHour = mIs24Hour ? 23 : 11 + minHour;
+                mListener.onValueChanged(HOURS, getHourOfDayFromLocalizedHour(
+                        MathUtils.constrain(hour, minHour, maxHour)));
+                return false;
+            }
+            mListener.onValueChanged(HOURS, getHourOfDayFromLocalizedHour(hour));
+            return true;
+        } catch (NumberFormatException e) {
+            // Do nothing since we cannot parse the input.
+            return false;
+        }
+    }
+
+    private boolean parseAndSetMinuteInternal(String input) {
+        try {
+            final int minutes = Integer.parseInt(input);
+            if (minutes < 0 || minutes > 59) {
+                mListener.onValueChanged(MINUTES, MathUtils.constrain(minutes, 0, 59));
+                return false;
+            }
+            mListener.onValueChanged(MINUTES, minutes);
+            return true;
+        } catch (NumberFormatException e) {
+            // Do nothing since we cannot parse the input.
+            return false;
+        }
+    }
+
+    private boolean isValidLocalizedHour(int localizedHour) {
+        final int minHour = mHourFormatStartsAtZero ? 0 : 1;
+        final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
+        return localizedHour >= minHour && localizedHour <= maxHour;
+    }
+
+    private int getHourOfDayFromLocalizedHour(int localizedHour) {
+        int hourOfDay = localizedHour;
+        if (mIs24Hour) {
+            if (!mHourFormatStartsAtZero && localizedHour == 24) {
+                hourOfDay = 0;
+            }
+        } else {
+            if (!mHourFormatStartsAtZero && localizedHour == 12) {
+                hourOfDay = 0;
+            }
+            if (mAmPmSpinner.getSelectedItemPosition() == 1) {
+                hourOfDay += 12;
+            }
+        }
+        return hourOfDay;
+    }
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4a8ec94..b18ca45 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,6 +17,10 @@
 package android.widget;
 
 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
+import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
+import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
+import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
 
 import android.R;
 import android.annotation.ColorInt;
@@ -142,6 +146,7 @@
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
@@ -166,6 +171,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Locale;
 
 /**
@@ -268,6 +274,7 @@
     static final String LOG_TAG = "TextView";
     static final boolean DEBUG_EXTRACT = false;
     static final boolean DEBUG_AUTOFILL = false;
+    private static final float[] TEMP_POSITION = new float[2];
 
     // Enum for the "typeface" XML parameter.
     // TODO: How can we get this from the XML instead of hardcoding it here?
@@ -9639,7 +9646,7 @@
         return new GestureDetector(mContext,
                 new GestureDetector.SimpleOnGestureListener() {
                     @Override
-                    public boolean onSingleTapConfirmed(MotionEvent e) {
+                    public boolean onSingleTapUp(MotionEvent e) {
                         if (shouldUseClickableSpanOnClickGestureDetector()) {
                             ClickableSpan[] links = ((Spannable) mText).getSpans(
                                     getSelectionStart(), getSelectionEnd(),
@@ -9736,9 +9743,6 @@
                 // Simple case: this is a single line.
                 final CharSequence text = getText();
                 structure.setText(text, getSelectionStart(), getSelectionEnd());
-                if (forAutoFill && isTextEditable()) {
-                    structure.setAutoFillValue(AutoFillValue.forText(text));
-                }
             } else {
                 // Complex case: multi-line, could be scrolled or within a scroll container
                 // so some lines are not visible.
@@ -9795,9 +9799,6 @@
                     text = text.subSequence(expandedTopChar, expandedBottomChar);
                 }
                 structure.setText(text, selStart - expandedTopChar, selEnd - expandedTopChar);
-                if (forAutoFill && isTextEditable()) {
-                    structure.setAutoFillValue(AutoFillValue.forText(text));
-                }
                 final int[] lineOffsets = new int[bottomLine - topLine + 1];
                 final int[] lineBaselines = new int[bottomLine - topLine + 1];
                 final int baselineOffset = getBaselineOffset();
@@ -9845,17 +9846,7 @@
         final CharSequence text = value.getTextValue();
 
         if (text != null && isTextEditable()) {
-            if (mAutoFillChangeWatcher == null || mAutoFillChangeWatcher.mOnAutoFill) {
-                setText(text, mBufferType, true, 0);
-            } else {
-                // Must disable listener first so it's not triggered.
-                mAutoFillChangeWatcher.mOnAutoFill = true;
-                try {
-                    setText(text, mBufferType, true, 0);
-                } finally {
-                    mAutoFillChangeWatcher.mOnAutoFill = false;
-                }
-            }
+            setText(text, mBufferType, true, 0);
         }
     }
 
@@ -9865,6 +9856,12 @@
         return isTextEditable() ? AutoFillType.forText(getInputType()) : null;
     }
 
+    @Override
+    @Nullable
+    public AutoFillValue getAutoFillValue() {
+        return isTextEditable() ? AutoFillValue.forText(getText()) : null;
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
@@ -9916,6 +9913,8 @@
                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
+            info.setAvailableExtraData(
+                    Arrays.asList(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
         }
 
         if (isFocused()) {
@@ -9952,6 +9951,164 @@
         }
     }
 
+    @Override
+    public void addExtraDataToAccessibilityNodeInfo(
+            AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
+        if (extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) {
+            int positionInfoStartIndex = arguments.getInt(
+                    EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, -1);
+            int positionInfoLength = arguments.getInt(
+                    EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH, -1);
+            if ((positionInfoLength <= 0) || (positionInfoStartIndex < 0)
+                    || (positionInfoStartIndex >= mText.length())) {
+                Log.e(LOG_TAG, "Invalid arguments for accessibility character locations");
+                return;
+            }
+            RectF[] boundingRects = new RectF[positionInfoLength];
+            final CursorAnchorInfo.Builder builder = new CursorAnchorInfo.Builder();
+            populateCharacterBounds(builder, positionInfoStartIndex,
+                    positionInfoStartIndex + positionInfoLength,
+                    viewportToContentHorizontalOffset(), viewportToContentVerticalOffset());
+            CursorAnchorInfo cursorAnchorInfo = builder.setMatrix(null).build();
+            if (mTempRect == null) mTempRect = new Rect();
+            Rect viewBoundsInScreen = mTempRect;
+            info.getBoundsInScreen(viewBoundsInScreen);
+            for (int i = 0; i < positionInfoLength; i++) {
+                int flags = cursorAnchorInfo.getCharacterBoundsFlags(positionInfoStartIndex + i);
+                if ((flags & FLAG_HAS_VISIBLE_REGION) == FLAG_HAS_VISIBLE_REGION) {
+                    RectF bounds = cursorAnchorInfo
+                            .getCharacterBounds(positionInfoStartIndex + i);
+                    if (bounds != null) {
+                        bounds.offset(viewBoundsInScreen.left, viewBoundsInScreen.top);
+                        boundingRects[i] = bounds;
+                    }
+                }
+            }
+            info.getExtras().putParcelableArray(extraDataKey, boundingRects);
+        }
+    }
+
+    /**
+     * Populate requested character bounds in a {@link CursorAnchorInfo.Builder}
+     *
+     * @param builder The builder to populate
+     * @param startIndex The starting character index to populate
+     * @param endIndex The ending character index to populate
+     * @param viewportToContentHorizontalOffset The horizontal offset from the viewport to the
+     * content
+     * @param viewportToContentVerticalOffset The vertical offset from the viewport to the content
+     * @hide
+     */
+    public void populateCharacterBounds(CursorAnchorInfo.Builder builder,
+            int startIndex, int endIndex, float viewportToContentHorizontalOffset,
+            float viewportToContentVerticalOffset) {
+        final int minLine = mLayout.getLineForOffset(startIndex);
+        final int maxLine = mLayout.getLineForOffset(endIndex - 1);
+        for (int line = minLine; line <= maxLine; ++line) {
+            final int lineStart = mLayout.getLineStart(line);
+            final int lineEnd = mLayout.getLineEnd(line);
+            final int offsetStart = Math.max(lineStart, startIndex);
+            final int offsetEnd = Math.min(lineEnd, endIndex);
+            final boolean ltrLine =
+                    mLayout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
+            final float[] widths = new float[offsetEnd - offsetStart];
+            mLayout.getPaint().getTextWidths(mText, offsetStart, offsetEnd, widths);
+            final float top = mLayout.getLineTop(line);
+            final float bottom = mLayout.getLineBottom(line);
+            for (int offset = offsetStart; offset < offsetEnd; ++offset) {
+                final float charWidth = widths[offset - offsetStart];
+                final boolean isRtl = mLayout.isRtlCharAt(offset);
+                final float primary = mLayout.getPrimaryHorizontal(offset);
+                final float secondary = mLayout.getSecondaryHorizontal(offset);
+                // TODO: This doesn't work perfectly for text with custom styles and
+                // TAB chars.
+                final float left;
+                final float right;
+                if (ltrLine) {
+                    if (isRtl) {
+                        left = secondary - charWidth;
+                        right = secondary;
+                    } else {
+                        left = primary;
+                        right = primary + charWidth;
+                    }
+                } else {
+                    if (!isRtl) {
+                        left = secondary;
+                        right = secondary + charWidth;
+                    } else {
+                        left = primary - charWidth;
+                        right = primary;
+                    }
+                }
+                // TODO: Check top-right and bottom-left as well.
+                final float localLeft = left + viewportToContentHorizontalOffset;
+                final float localRight = right + viewportToContentHorizontalOffset;
+                final float localTop = top + viewportToContentVerticalOffset;
+                final float localBottom = bottom + viewportToContentVerticalOffset;
+                final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop);
+                final boolean isBottomRightVisible =
+                        isPositionVisible(localRight, localBottom);
+                int characterBoundsFlags = 0;
+                if (isTopLeftVisible || isBottomRightVisible) {
+                    characterBoundsFlags |= FLAG_HAS_VISIBLE_REGION;
+                }
+                if (!isTopLeftVisible || !isBottomRightVisible) {
+                    characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+                }
+                if (isRtl) {
+                    characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+                }
+                // Here offset is the index in Java chars.
+                builder.addCharacterBounds(offset, localLeft, localTop, localRight,
+                        localBottom, characterBoundsFlags);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isPositionVisible(final float positionX, final float positionY) {
+        synchronized (TEMP_POSITION) {
+            final float[] position = TEMP_POSITION;
+            position[0] = positionX;
+            position[1] = positionY;
+            View view = this;
+
+            while (view != null) {
+                if (view != this) {
+                    // Local scroll is already taken into account in positionX/Y
+                    position[0] -= view.getScrollX();
+                    position[1] -= view.getScrollY();
+                }
+
+                if (position[0] < 0 || position[1] < 0 || position[0] > view.getWidth()
+                        || position[1] > view.getHeight()) {
+                    return false;
+                }
+
+                if (!view.getMatrix().isIdentity()) {
+                    view.getMatrix().mapPoints(position);
+                }
+
+                position[0] += view.getLeft();
+                position[1] += view.getTop();
+
+                final ViewParent parent = view.getParent();
+                if (parent instanceof View) {
+                    view = (View) parent;
+                } else {
+                    // We've reached the ViewRoot, stop iterating
+                    view = null;
+                }
+            }
+        }
+
+        // We've been able to walk up the view hierarchy and the position was never clipped
+        return true;
+    }
+
     /**
      * Performs an accessibility action after it has been offered to the
      * delegate.
@@ -10724,14 +10881,6 @@
      * @hide
      */
     protected void viewClicked(InputMethodManager imm) {
-        final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
-        if (afm != null) {
-            if (DEBUG_AUTOFILL) Log.v(LOG_TAG, "viewClicked(): id=" + getAccessibilityViewId());
-
-            // TODO(b/33197203): integrate with onFocus and/or move to view?
-            afm.updateAutoFillInput(this, AutoFillManager.FLAG_UPDATE_UI_SHOW);
-        }
-
         if (imm != null) {
             imm.viewClicked(this);
         }
@@ -11213,7 +11362,6 @@
     // TODO(b/33197203): implements SpanWatcher too?
     private final class AutoFillChangeWatcher implements TextWatcher {
 
-        private boolean mOnAutoFill;
         private final AutoFillManager mAfm = mContext.getSystemService(AutoFillManager.class);
 
         @Override
@@ -11226,18 +11374,11 @@
 
         @Override
         public void afterTextChanged(Editable s) {
-            if (mOnAutoFill) {
-                if (DEBUG_AUTOFILL) {
-                    Log.v(LOG_TAG, "AutoFillChangeWatcher.afterTextChanged() skipped during "
-                            + "autoFill(): s=" + s);
-                }
-                return;
-            }
             if (mAfm != null) {
                 if (DEBUG_AUTOFILL) {
                     Log.v(LOG_TAG, "AutoFillChangeWatcher.afterTextChanged(): s=" + s);
                 }
-                mAfm.onValueChanged(TextView.this, AutoFillValue.forText(s));
+                mAfm.valueChanged(TextView.this);
             }
         }
     }
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e6cd798..9f38b04 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -278,6 +278,16 @@
         return mDelegate.getBaseline();
     }
 
+    /**
+     * Validates whether current input by the user is a valid time based on the locale. TimePicker
+     * will show an error message to the user if the time is not valid.
+     *
+     * @return {@code true} if the input is valid, {@code false} otherwise
+     */
+    public boolean validateInput() {
+        return mDelegate.validateInput();
+    }
+
     @Override
     protected Parcelable onSaveInstanceState() {
         Parcelable superState = super.onSaveInstanceState();
@@ -341,6 +351,8 @@
         void setIs24Hour(boolean is24Hour);
         boolean is24Hour();
 
+        boolean validateInput();
+
         void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
 
         void setEnabled(boolean enabled);
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 1d37a21..3a09063 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -16,12 +16,14 @@
 
 package android.widget;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.icu.text.DecimalFormatSymbols;
 import android.os.Parcelable;
 import android.text.SpannableStringBuilder;
 import android.text.format.DateFormat;
@@ -40,11 +42,14 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.widget.RadialTimePickerView.OnValueSelectedListener;
+import android.widget.TextInputTimePickerView.OnValueTypedListener;
 
 import com.android.internal.R;
 import com.android.internal.widget.NumericTextView;
 import com.android.internal.widget.NumericTextView.OnValueChangedListener;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Calendar;
 
 /**
@@ -58,6 +63,13 @@
      */
     private static final long DELAY_COMMIT_MILLIS = 2000;
 
+    @IntDef({FROM_EXTERNAL_API, FROM_RADIAL_PICKER, FROM_INPUT_PICKER})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ChangeSource {}
+    private static final int FROM_EXTERNAL_API = 0;
+    private static final int FROM_RADIAL_PICKER = 1;
+    private static final int FROM_INPUT_PICKER = 2;
+
     // Index used by RadialPickerLayout
     private static final int HOUR_INDEX = RadialTimePickerView.HOURS;
     private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES;
@@ -78,6 +90,15 @@
     private final RadialTimePickerView mRadialTimePickerView;
     private final TextView mSeparatorView;
 
+    private boolean mRadialPickerModeEnabled = true;
+    private final ImageButton mRadialTimePickerModeButton;
+    private final String mRadialTimePickerModeEnabledDescription;
+    private final String mTextInputPickerModeEnabledDescription;
+    private final View mRadialTimePickerHeader;
+    private final View mTextInputPickerHeader;
+
+    private final TextInputTimePickerView mTextInputPickerView;
+
     private final Calendar mTempCalendar;
 
     // Accessibility strings.
@@ -116,8 +137,8 @@
         final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
                 R.layout.time_picker_material);
         final View mainView = inflater.inflate(layoutResourceId, delegator);
-        final View headerView = mainView.findViewById(R.id.time_header);
-        headerView.setOnTouchListener(new NearestTouchDelegate());
+        mRadialTimePickerHeader = mainView.findViewById(R.id.time_header);
+        mRadialTimePickerHeader.setOnTouchListener(new NearestTouchDelegate());
 
         // Set up hour/minute labels.
         mHourView = (NumericTextView) mainView.findViewById(R.id.hours);
@@ -170,6 +191,8 @@
             headerTextColor = a.getColorStateList(R.styleable.TimePicker_headerTextColor);
         }
 
+        mTextInputPickerHeader = mainView.findViewById(R.id.input_header);
+
         if (headerTextColor != null) {
             mHourView.setTextColor(headerTextColor);
             mSeparatorView.setTextColor(headerTextColor);
@@ -180,7 +203,10 @@
 
         // Set up header background, if available.
         if (a.hasValueOrEmpty(R.styleable.TimePicker_headerBackground)) {
-            headerView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
+            mRadialTimePickerHeader.setBackground(a.getDrawable(
+                    R.styleable.TimePicker_headerBackground));
+            mTextInputPickerHeader.setBackground(a.getDrawable(
+                    R.styleable.TimePicker_headerBackground));
         }
 
         a.recycle();
@@ -189,6 +215,22 @@
         mRadialTimePickerView.applyAttributes(attrs, defStyleAttr, defStyleRes);
         mRadialTimePickerView.setOnValueSelectedListener(mOnValueSelectedListener);
 
+        mTextInputPickerView = (TextInputTimePickerView) mainView.findViewById(R.id.input_mode);
+        mTextInputPickerView.setListener(mOnValueTypedListener);
+
+        mRadialTimePickerModeButton =
+                (ImageButton) mainView.findViewById(R.id.toggle_mode);
+        mRadialTimePickerModeButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                toggleRadialPickerMode();
+            }
+        });
+        mRadialTimePickerModeEnabledDescription = context.getResources().getString(
+                R.string.time_picker_radial_mode_description);
+        mTextInputPickerModeEnabledDescription = context.getResources().getString(
+                R.string.time_picker_text_input_mode_description);
+
         mAllowAutoAdvance = true;
 
         updateHourFormat();
@@ -200,6 +242,34 @@
         initialize(currentHour, currentMinute, mIs24Hour, HOUR_INDEX);
     }
 
+    private void toggleRadialPickerMode() {
+        if (mRadialPickerModeEnabled) {
+            mRadialTimePickerView.setVisibility(View.GONE);
+            mRadialTimePickerHeader.setVisibility(View.GONE);
+            mTextInputPickerHeader.setVisibility(View.VISIBLE);
+            mTextInputPickerView.setVisibility(View.VISIBLE);
+            mRadialTimePickerModeButton.setImageResource(R.drawable.btn_event_material);
+            mRadialTimePickerModeButton.setContentDescription(
+                    mRadialTimePickerModeEnabledDescription);
+            mRadialPickerModeEnabled = false;
+        } else {
+            mRadialTimePickerView.setVisibility(View.VISIBLE);
+            mRadialTimePickerHeader.setVisibility(View.VISIBLE);
+            mTextInputPickerHeader.setVisibility(View.GONE);
+            mTextInputPickerView.setVisibility(View.GONE);
+            mRadialTimePickerModeButton.setImageResource(R.drawable.btn_keyboard_key_material);
+            mRadialTimePickerModeButton.setContentDescription(
+                    mTextInputPickerModeEnabledDescription);
+            updateTextInputPicker();
+            mRadialPickerModeEnabled = true;
+        }
+    }
+
+    @Override
+    public boolean validateInput() {
+        return mTextInputPickerView.validateInput();
+    }
+
     /**
      * Ensures that a TextView is wide enough to contain its text without
      * wrapping or clipping. Measures the specified view and sets the minimum
@@ -249,9 +319,16 @@
         final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
         mHourView.setRange(minHour, maxHour);
         mHourView.setShowLeadingZeroes(mHourFormatShowLeadingZero);
+
+        final String[] digits = DecimalFormatSymbols.getInstance(mLocale).getDigitStrings();
+        int maxCharLength = 0;
+        for (int i = 0; i < 10; i++) {
+            maxCharLength = Math.max(maxCharLength, digits[i].length());
+        }
+        mTextInputPickerView.setHourFormat(maxCharLength * 2);
     }
 
-    private static final CharSequence obtainVerbatim(String text) {
+    static final CharSequence obtainVerbatim(String text) {
         return new SpannableStringBuilder().append(text,
                 new TtsSpan.VerbatimBuilder(text).build(), 0);
     }
@@ -333,10 +410,16 @@
         updateHeaderSeparator();
         updateHeaderMinute(mCurrentMinute, false);
         updateRadialPicker(index);
+        updateTextInputPicker();
 
         mDelegator.invalidate();
     }
 
+    private void updateTextInputPicker() {
+        mTextInputPickerView.updateTextInputValues(getLocalizedHour(mCurrentHour), mCurrentMinute,
+                mCurrentHour < 12 ? AM : PM, mIs24Hour, mHourFormatStartsAtZero);
+    }
+
     private void updateRadialPicker(int index) {
         mRadialTimePickerView.initialize(mCurrentHour, mCurrentMinute, mIs24Hour);
         setCurrentItemShowing(index, false, true);
@@ -381,10 +464,10 @@
      */
     @Override
     public void setHour(int hour) {
-        setHourInternal(hour, false, true);
+        setHourInternal(hour, FROM_EXTERNAL_API, true);
     }
 
-    private void setHourInternal(int hour, boolean isFromPicker, boolean announce) {
+    private void setHourInternal(int hour, @ChangeSource int source, boolean announce) {
         if (mCurrentHour == hour) {
             return;
         }
@@ -393,10 +476,13 @@
         updateHeaderHour(hour, announce);
         updateHeaderAmPm();
 
-        if (!isFromPicker) {
+        if (source != FROM_RADIAL_PICKER) {
             mRadialTimePickerView.setCurrentHour(hour);
             mRadialTimePickerView.setAmOrPm(hour < 12 ? AM : PM);
         }
+        if (source != FROM_INPUT_PICKER) {
+            updateTextInputPicker();
+        }
 
         mDelegator.invalidate();
         onTimeChanged();
@@ -424,10 +510,10 @@
      */
     @Override
     public void setMinute(int minute) {
-        setMinuteInternal(minute, false);
+        setMinuteInternal(minute, FROM_EXTERNAL_API);
     }
 
-    private void setMinuteInternal(int minute, boolean isFromPicker) {
+    private void setMinuteInternal(int minute, @ChangeSource int source) {
         if (mCurrentMinute == minute) {
             return;
         }
@@ -435,9 +521,12 @@
         mCurrentMinute = minute;
         updateHeaderMinute(minute, true);
 
-        if (!isFromPicker) {
+        if (source != FROM_RADIAL_PICKER) {
             mRadialTimePickerView.setCurrentMinute(minute);
         }
+        if (source != FROM_INPUT_PICKER) {
+            updateTextInputPicker();
+        }
 
         mDelegator.invalidate();
         onTimeChanged();
@@ -661,6 +750,7 @@
             separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
         }
         mSeparatorView.setText(separatorText);
+        mTextInputPickerView.updateSeparator(separatorText);
     }
 
     static private int lastIndexOfAny(String str, char[] any) {
@@ -712,7 +802,7 @@
 
         if (mRadialTimePickerView.setAmOrPm(amOrPm)) {
             mCurrentHour = getHour();
-
+            updateTextInputPicker();
             if (mOnTimeChangedListener != null) {
                 mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
             }
@@ -726,7 +816,7 @@
             switch (pickerType) {
                 case RadialTimePickerView.HOURS:
                     final boolean isTransition = mAllowAutoAdvance && autoAdvance;
-                    setHourInternal(newValue, true, !isTransition);
+                    setHourInternal(newValue, FROM_RADIAL_PICKER, !isTransition);
                     if (isTransition) {
                         setCurrentItemShowing(MINUTE_INDEX, true, false);
 
@@ -735,7 +825,7 @@
                     }
                     break;
                 case RadialTimePickerView.MINUTES:
-                    setMinuteInternal(newValue, true);
+                    setMinuteInternal(newValue, FROM_RADIAL_PICKER);
                     break;
             }
 
@@ -745,6 +835,23 @@
         }
     };
 
+    private final OnValueTypedListener mOnValueTypedListener = new OnValueTypedListener() {
+        @Override
+        public void onValueChanged(int pickerType, int newValue) {
+            switch (pickerType) {
+                case TextInputTimePickerView.HOURS:
+                    setHourInternal(newValue, FROM_INPUT_PICKER, false);
+                    break;
+                case TextInputTimePickerView.MINUTES:
+                    setMinuteInternal(newValue, FROM_INPUT_PICKER);
+                    break;
+                case TextInputTimePickerView.AMPM:
+                    setAmOrPm(newValue);
+                    break;
+            }
+        }
+    };
+
     /** Listener for keyboard interaction. */
     private final OnValueChangedListener mDigitEnteredListener = new OnValueChangedListener() {
         @Override
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 4634631..7ef54a5 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -86,7 +86,7 @@
         inflater.inflate(layoutResourceId, mDelegator, true);
 
         // hour
-        mHourSpinner = delegator.findViewById(R.id.hour);
+        mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
         mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
             public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                 updateInputState();
@@ -100,17 +100,17 @@
                 onTimeChanged();
             }
         });
-        mHourSpinnerInput = mHourSpinner.findViewById(R.id.numberpicker_input);
+        mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
         mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
         // divider (only for the new widget style)
-        mDivider = mDelegator.findViewById(R.id.divider);
+        mDivider = (TextView) mDelegator.findViewById(R.id.divider);
         if (mDivider != null) {
             setDividerText();
         }
 
         // minute
-        mMinuteSpinner = mDelegator.findViewById(R.id.minute);
+        mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
         mMinuteSpinner.setMinValue(0);
         mMinuteSpinner.setMaxValue(59);
         mMinuteSpinner.setOnLongPressUpdateInterval(100);
@@ -138,7 +138,7 @@
                 onTimeChanged();
             }
         });
-        mMinuteSpinnerInput = mMinuteSpinner.findViewById(R.id.numberpicker_input);
+        mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
         mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
         // Get the localized am/pm strings and use them in the spinner.
@@ -173,13 +173,13 @@
                     onTimeChanged();
                 }
             });
-            mAmPmSpinnerInput = mAmPmSpinner.findViewById(R.id.numberpicker_input);
+            mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
             mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
         }
 
         if (isAmPmAtStart()) {
             // Move the am/pm view to the beginning
-            ViewGroup amPmParent = delegator.findViewById(R.id.timePickerLayout);
+            ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
             amPmParent.removeView(amPmView);
             amPmParent.addView(amPmView, 0);
             // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
@@ -219,6 +219,11 @@
         }
     }
 
+    @Override
+    public boolean validateInput() {
+        return true;
+    }
+
     private void getHourFormatData() {
         final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mLocale,
                 (mIs24HourView) ? "Hm" : "hm");
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index bf0601d..789e60b 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -299,7 +299,7 @@
         if (mNextView == null) {
             throw new RuntimeException("This Toast was not created with Toast.makeText()");
         }
-        TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
+        TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
         if (tv == null) {
             throw new RuntimeException("This Toast was not created with Toast.makeText()");
         }
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 1a3ca86..69b79971 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -264,7 +264,7 @@
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(com.android.internal.R.layout.zoom_container, container);
 
-        mControls = container.findViewById(com.android.internal.R.id.zoomControls);
+        mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls);
         mControls.setOnZoomInClickListener(new OnClickListener() {
             public void onClick(View v) {
                 dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ab1d9b9..4014217 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -36,7 +36,6 @@
 import com.android.internal.content.PackageMonitor;
 
 import android.app.ActivityManager;
-import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -115,6 +114,7 @@
 
     private static final String TAG = "ResolverActivity";
     private static final boolean DEBUG = false;
+    private Runnable mPostListBuildRunnable;
 
     private boolean mRegistered;
     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -419,7 +419,9 @@
 
     protected CharSequence getTitleForAction(String action, int defaultTitleRes) {
         final ActionTitle title = mResolvingHome ? ActionTitle.HOME : ActionTitle.forAction(action);
-        final boolean named = mAdapter.hasFilteredItem();
+        // While there may already be a filtered item, we can only use it in the title if the list
+        // is already sorted and all information relevant to it is already in the list.
+        final boolean named = mAdapter.getFilteredPosition() > 0;
         if (title == ActionTitle.DEFAULT && defaultTitleRes != 0) {
             return getString(defaultTitleRes);
         } else {
@@ -510,6 +512,9 @@
         if (!isChangingConfigurations() && mPickOptionRequest != null) {
             mPickOptionRequest.cancel();
         }
+        if (mPostListBuildRunnable != null) {
+            getMainThreadHandler().removeCallbacks(mPostListBuildRunnable);
+        }
     }
 
     @Override
@@ -590,6 +595,9 @@
         }
 
         TargetInfo target = mAdapter.targetInfoForPosition(which, filtered);
+        if (target == null) {
+            return;
+        }
         if (onTargetSelected(target, always)) {
             if (always && filtered) {
                 MetricsLogger.action(
@@ -880,15 +888,15 @@
         }
 
         setContentView(mLayoutId);
-        if (count > 0 || !rebuildCompleted) {
-            mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
-            onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption);
-        } else {
+        mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
+
+        if (count == 0 && mAdapter.mPlaceholderCount == 0) {
             final TextView empty = (TextView) findViewById(R.id.empty);
             empty.setVisibility(View.VISIBLE);
-
-            mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
             mAdapterView.setVisibility(View.GONE);
+        } else {
+            mAdapterView.setVisibility(View.VISIBLE);
+            onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption);
         }
         return false;
     }
@@ -917,16 +925,23 @@
     }
 
     public void setTitleAndIcon() {
-        if (mTitle == null) {
-            mTitle = getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId);
-        }
-
-        if (!TextUtils.isEmpty(mTitle)) {
+        if (mAdapter.getCount() == 0 && mAdapter.mPlaceholderCount == 0) {
             final TextView titleView = (TextView) findViewById(R.id.title);
             if (titleView != null) {
-                titleView.setText(mTitle);
+                titleView.setVisibility(View.GONE);
             }
-            setTitle(mTitle);
+        }
+
+        CharSequence title = mTitle != null
+                ? mTitle
+                : getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId);
+
+        if (!TextUtils.isEmpty(title)) {
+            final TextView titleView = (TextView) findViewById(R.id.title);
+            if (titleView != null) {
+                titleView.setText(title);
+            }
+            setTitle(title);
 
             // Try to initialize the title icon if we have a view for it and a title to match
             final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon);
@@ -963,9 +978,17 @@
             }
         }
 
-        if (mAdapter.hasFilteredItem()) {
+        if (mAdapter.getFilteredPosition() >= 0) {
             setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false);
             mOnceButton.setEnabled(true);
+            return;
+        }
+
+        // When the items load in, if an item was already selected, enable the buttons
+        if (mAdapterView != null
+                && mAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
+            setAlwaysButtonEnabled(true, mAdapterView.getCheckedItemPosition(), true);
+            mOnceButton.setEnabled(true);
         }
     }
 
@@ -1234,6 +1257,7 @@
         private DisplayResolveInfo mOtherProfile;
         private boolean mHasExtendedInfo;
         private ResolverListController mResolverListController;
+        private int mPlaceholderCount;
 
         protected final LayoutInflater mInflater;
 
@@ -1265,6 +1289,10 @@
             }
         }
 
+        public void setPlaceholderCount(int count) {
+            mPlaceholderCount = count;
+        }
+
         public DisplayResolveInfo getFilteredItem() {
             if (mFilterLastUsed && mLastChosenPosition >= 0) {
                 // Not using getItem since it offsets to dodge this position for the list
@@ -1350,6 +1378,7 @@
                 }
 
                 if (N > 1) {
+                    setPlaceholderCount(currentResolveList.size());
                     AsyncTask<List<ResolvedComponentInfo>,
                             Void,
                             List<ResolvedComponentInfo>> sortingTask =
@@ -1366,13 +1395,26 @@
                         @Override
                         protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
                             processSortedList(sortedComponents);
-                            onPrepareAdapterView(mAdapterView, mAdapter, mAlwaysUseOption);
                             if (mProfileView != null) {
                                 bindProfileView();
                             }
+                            notifyDataSetChanged();
                         }
                     };
                     sortingTask.execute(currentResolveList);
+                    if (mPostListBuildRunnable == null) {
+                        mPostListBuildRunnable = new Runnable() {
+                            @Override
+                            public void run() {
+                                setTitleAndIcon();
+                                resetAlwaysOrOnceButtonBar();
+                                onListRebuilt();
+                                disableLastChosenIfNeeded();
+                                mPostListBuildRunnable = null;
+                            }
+                        };
+                        getMainThreadHandler().post(mPostListBuildRunnable);
+                    }
                     return false;
                 } else {
                     processSortedList(currentResolveList);
@@ -1563,21 +1605,33 @@
             }
         }
 
+        @Nullable
         public ResolveInfo resolveInfoForPosition(int position, boolean filtered) {
-            return (filtered ? getItem(position) : mDisplayList.get(position))
-                    .getResolveInfo();
+            TargetInfo target = targetInfoForPosition(position, filtered);
+            if (target != null) {
+                return target.getResolveInfo();
+             }
+             return null;
         }
 
+        @Nullable
         public TargetInfo targetInfoForPosition(int position, boolean filtered) {
-            return filtered ? getItem(position) : mDisplayList.get(position);
+            if (filtered) {
+                return getItem(position);
+            }
+            if (mDisplayList.size() > position) {
+                return mDisplayList.get(position);
+            }
+            return null;
         }
 
         public int getCount() {
-            int result = mDisplayList.size();
+            int totalSize = mDisplayList == null || mDisplayList.isEmpty() ? mPlaceholderCount :
+                    mDisplayList.size();
             if (mFilterLastUsed && mLastChosenPosition >= 0) {
-                result--;
+                totalSize--;
             }
-            return result;
+            return totalSize;
         }
 
         public int getUnfilteredCount() {
@@ -1592,11 +1646,16 @@
             return mDisplayList.get(index);
         }
 
+        @Nullable
         public TargetInfo getItem(int position) {
             if (mFilterLastUsed && mLastChosenPosition >= 0 && position >= mLastChosenPosition) {
                 position++;
             }
-            return mDisplayList.get(position);
+            if (mDisplayList.size() > position) {
+                return mDisplayList.get(position);
+            } else {
+                return null;
+            }
         }
 
         public long getItemId(int position) {
@@ -1660,6 +1719,11 @@
 
         private void onBindView(View view, TargetInfo info) {
             final ViewHolder holder = (ViewHolder) view.getTag();
+            if (info == null) {
+                holder.icon.setImageDrawable(
+                        getDrawable(R.drawable.resolver_icon_placeholder));
+                return;
+            }
             final CharSequence label = info.getDisplayLabel();
             if (!TextUtils.equals(holder.text.getText(), label)) {
                 holder.text.setText(info.getDisplayLabel());
@@ -1770,6 +1834,11 @@
                 // Header views don't count.
                 return;
             }
+            // If we're still loading, we can't yet enable the buttons.
+            if (mAdapter.resolveInfoForPosition(position, true) == null) {
+                return;
+            }
+
             final int checkedPos = mAdapterView.getCheckedItemPosition();
             final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
             if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
diff --git a/core/java/com/android/internal/app/procstats/PssTable.java b/core/java/com/android/internal/app/procstats/PssTable.java
index b6df983..de5f673 100644
--- a/core/java/com/android/internal/app/procstats/PssTable.java
+++ b/core/java/com/android/internal/app/procstats/PssTable.java
@@ -96,7 +96,7 @@
             }
 
             val = getValue(key, PSS_USS_AVERAGE);
-            setValue(key, PSS_AVERAGE,
+            setValue(key, PSS_USS_AVERAGE,
                     (long)(((val*(double)count)+(avgUss*(double)inCount)) / (count+inCount)));
 
             val = getValue(key, PSS_USS_MAXIMUM);
diff --git a/core/java/com/android/internal/policy/PipMotionHelper.java b/core/java/com/android/internal/policy/PipMotionHelper.java
deleted file mode 100644
index 944cd32..0000000
--- a/core/java/com/android/internal/policy/PipMotionHelper.java
+++ /dev/null
@@ -1,91 +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 com.android.internal.policy;
-
-import android.animation.RectEvaluator;
-import android.animation.ValueAnimator;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
-
-/**
- * A helper to animate the PIP.
- */
-public class PipMotionHelper {
-
-    private static final String TAG = "PipMotionHelper";
-
-    private static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
-    private static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
-    private static final int DEFAULT_DURATION = 225;
-
-    private IActivityManager mActivityManager;
-    private Handler mHandler;
-
-    public PipMotionHelper(Handler handler) {
-        mHandler = handler;
-    }
-
-    /**
-     * Moves the PIP to give given {@param bounds}.
-     */
-    public void resizeToBounds(Rect toBounds) {
-        mHandler.post(() -> {
-            if (mActivityManager == null) {
-                mActivityManager = ActivityManager.getService();
-            }
-            try {
-                mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Could not move pinned stack to bounds: " + toBounds, e);
-            }
-        });
-    }
-
-    /**
-     * Creates an animation to move the PIP to give given {@param toBounds} with the default
-     * animation properties.
-     */
-    public ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds) {
-        return createAnimationToBounds(fromBounds, toBounds, DEFAULT_DURATION, FAST_OUT_SLOW_IN,
-                null);
-    }
-
-    /**
-     * Creates an animation to move the PIP to give given {@param toBounds}.
-     */
-    public ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds, int duration,
-            Interpolator interpolator, ValueAnimator.AnimatorUpdateListener updateListener) {
-        ValueAnimator anim = ValueAnimator.ofObject(RECT_EVALUATOR, fromBounds, toBounds);
-        anim.setDuration(duration);
-        anim.setInterpolator(interpolator);
-        anim.addUpdateListener((ValueAnimator animation) -> {
-            resizeToBounds((Rect) animation.getAnimatedValue());
-        });
-        if (updateListener != null) {
-            anim.addUpdateListener(updateListener);
-        }
-        return anim;
-    }
-
-
-}
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index ec92aa9..bf047c1 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -84,13 +84,6 @@
     }
 
     /**
-     * Enables snapping to the closest edge.
-     */
-    public void setSnapToEdge(boolean snapToEdge) {
-        mSnapMode = snapToEdge ? SNAP_MODE_EDGE : mDefaultSnapMode;
-    }
-
-    /**
      * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at
      * the given {@param velocityX} and {@param velocityY}.  The {@param movementBounds} should be
      * those for the given {@param stackBounds}.
@@ -233,6 +226,21 @@
     }
 
     /**
+     * Adjusts {@param movementBoundsOut} so that it is the movement bounds for the given
+     * {@param stackBounds}.
+     */
+    public void getMovementBounds(Rect stackBounds, Rect insetBounds, Rect movementBoundsOut,
+            int imeHeight) {
+        // Adjust the right/bottom to ensure the stack bounds never goes offscreen
+        movementBoundsOut.set(insetBounds);
+        movementBoundsOut.right = Math.max(insetBounds.left, insetBounds.right -
+                stackBounds.width());
+        movementBoundsOut.bottom = Math.max(insetBounds.top, insetBounds.bottom -
+                stackBounds.height());
+        movementBoundsOut.bottom -= imeHeight;
+    }
+
+    /**
      * @return the closest point in {@param points} to the given {@param x} and {@param y}.
      */
     private Point findClosestPoint(int x, int y, Point[] points) {
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 20f10b3..9cbbc5a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -53,9 +53,6 @@
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
             boolean showImeSwitcher);
     void setWindowState(int window, int state);
-    void buzzBeepBlinked();
-    void notificationLightOff();
-    void notificationLightPulse(int argb, int millisOn, int millisOff);
 
     void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
     void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index a9a6364..cb3a250 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -435,10 +435,6 @@
         }
     }
 
-    public static <T> boolean contains(@Nullable ArraySet<T> cur, T val) {
-        return (cur != null) ? cur.contains(val) : false;
-    }
-
     public static @NonNull <T> ArrayList<T> add(@Nullable ArrayList<T> cur, T val) {
         if (cur == null) {
             cur = new ArrayList<>();
@@ -459,6 +455,16 @@
         }
     }
 
+    /**
+     * Returns the given list, or an immutable empty list if the provided list is null
+     *
+     * @see Collections#emptyList
+     */
+
+    public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) {
+        return cur == null ? Collections.emptyList() : cur;
+    }
+
     public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
         return (cur != null) ? cur.contains(val) : false;
     }
diff --git a/core/java/android/service/autofill/CallbackHelper.java b/core/java/com/android/internal/util/ObjectUtils.java
similarity index 65%
copy from core/java/android/service/autofill/CallbackHelper.java
copy to core/java/com/android/internal/util/ObjectUtils.java
index ded8f97..d109a5a 100644
--- a/core/java/android/service/autofill/CallbackHelper.java
+++ b/core/java/com/android/internal/util/ObjectUtils.java
@@ -13,18 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.autofill;
 
-import java.io.PrintWriter;
 
-final class CallbackHelper {
+package com.android.internal.util;
 
-    static interface Dumpable {
-        void dump(String prefix, PrintWriter pw);
-        void setFinalizer(Finalizer f);
-    }
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 
-    static interface Finalizer {
-        void gone();
+/** @hide */
+public class ObjectUtils {
+    private ObjectUtils() {}
+
+    @NonNull
+    public static <T> T firstNotNull(@Nullable T a, @NonNull T b) {
+        return a != null ? a : Preconditions.checkNotNull(b);
     }
 }
diff --git a/core/java/com/android/internal/widget/DrawingSpace.java b/core/java/com/android/internal/widget/DrawingSpace.java
deleted file mode 100644
index b8222db..0000000
--- a/core/java/com/android/internal/widget/DrawingSpace.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * Implementation of {@link android.widget.Space} that uses normal View drawing
- * rather than a no-op. Useful for dialogs and other places where the base View
- * class is too greedy when measured with AT_MOST.
- */
-public final class DrawingSpace extends View {
-    public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public DrawingSpace(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public DrawingSpace(Context context) {
-        this(context, null);
-    }
-
-    /**
-     * Compare to: {@link View#getDefaultSize(int, int)}
-     * <p>
-     * If mode is AT_MOST, return the child size instead of the parent size
-     * (unless it is too big).
-     */
-    private static int getDefaultSizeNonGreedy(int size, int measureSpec) {
-        int result = size;
-        int specMode = MeasureSpec.getMode(measureSpec);
-        int specSize = MeasureSpec.getSize(measureSpec);
-
-        switch (specMode) {
-            case MeasureSpec.UNSPECIFIED:
-                result = size;
-                break;
-            case MeasureSpec.AT_MOST:
-                result = Math.min(size, specSize);
-                break;
-            case MeasureSpec.EXACTLY:
-                result = specSize;
-                break;
-        }
-        return result;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        setMeasuredDimension(
-                getDefaultSizeNonGreedy(getSuggestedMinimumWidth(), widthMeasureSpec),
-                getDefaultSizeNonGreedy(getSuggestedMinimumHeight(), heightMeasureSpec));
-    }
-}
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 53fa7ab..4fd19c3 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -92,14 +92,13 @@
     }
 
     @Override
-    protected <T extends View> T findViewByPredicateTraversal(
-            Predicate<View> predicate, View childToSkip) {
+    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
         View v = super.findViewByPredicateTraversal(predicate, childToSkip);
         if (v == null && mTopPanel != null && mTopPanel != childToSkip
                 && !mTopPanel.isRootNamespace()) {
-            return (T) mTopPanel.findViewByPredicate(predicate);
+            return mTopPanel.findViewByPredicate(predicate);
         }
-        return (T) v;
+        return v;
     }
 
     @Override
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index fadf8a4..6cf5ccf 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -30,6 +30,7 @@
 #include <binder/Parcel.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/ISurfaceComposer.h>
+#include <hardware/gralloc1.h>
 #include <ui/GraphicBuffer.h>
 
 #include <private/gui/ComposerService.h>
@@ -96,10 +97,15 @@
         }
         return NULL;
     }
-    uint32_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0);
+    uint64_t producerUsage = 0;
+    uint64_t consumerUsage = 0;
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage, 0, &producerUsage,
+            &consumerUsage);
     status_t error;
     sp<GraphicBuffer> buffer(alloc->createGraphicBuffer(width, height, pixelFormat,
-            layers, grallocUsage, &error));
+            layers, producerUsage, consumerUsage,
+            std::string("HardwareBuffer pid [") + std::to_string(getpid()) +"]",
+            &error));
     if (buffer == NULL) {
         if (kDebugGraphicBuffer) {
             ALOGW("createGraphicBuffer() failed in HardwareBuffer.create()");
@@ -158,7 +164,7 @@
     jobject clazz, jlong nativeObject) {
     GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
     return android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
-            buffer->getUsage());
+            buffer->getUsage(), buffer->getUsage());
 }
 
 // ----------------------------------------------------------------------------
@@ -261,52 +267,58 @@
     }
 }
 
-uint32_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0,
-        uint64_t usage1) {
-    uint32_t bits = 0;
+void android_hardware_HardwareBuffer_convertToGrallocUsageBits(uint64_t usage0,
+        uint64_t usage1, uint64_t* outProducerUsage,
+        uint64_t* outConsumerUsage) {
+    *outProducerUsage = 0;
+    *outConsumerUsage = 0;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ))
-        bits |= GRALLOC_USAGE_SW_READ_RARELY;
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN))
-        bits |= GRALLOC_USAGE_SW_READ_OFTEN;
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE))
-        bits |= GRALLOC_USAGE_SW_WRITE_RARELY;
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN))
-        bits |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE))
-        bits |= GRALLOC_USAGE_HW_TEXTURE;
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT))
-        bits |= GRALLOC_USAGE_HW_RENDER;
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
     // Not sure what this should be.
-    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0;
-    //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER) bits |= 0;
+    //if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP)) bits |= 0;
+    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER))
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE))
-        bits |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+        *outConsumerUsage |= GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER;
     if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT))
-        bits |= GRALLOC_USAGE_PROTECTED;
-
-    (void)usage1;
-
-    return bits;
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
+    if (containsBits(usage0, AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA))
+        *outProducerUsage |= GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA;
 }
 
-uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(uint64_t usage0) {
+uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
+        uint64_t producerUsage, uint64_t consumerUsage) {
     uint64_t bits = 0;
-    if (containsBits(usage0, GRALLOC_USAGE_SW_READ_RARELY))
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ))
         bits |= AHARDWAREBUFFER_USAGE0_CPU_READ;
-    if (containsBits(usage0, GRALLOC_USAGE_SW_READ_OFTEN))
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN))
         bits |= AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN;
-    if (containsBits(usage0, GRALLOC_USAGE_SW_WRITE_RARELY))
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE))
         bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE;
-    if (containsBits(usage0, GRALLOC_USAGE_SW_WRITE_OFTEN))
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN))
         bits |= AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN;
-    if (containsBits(usage0, GRALLOC_USAGE_HW_TEXTURE))
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE))
         bits |= AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE;
-    if (containsBits(usage0, GRALLOC_USAGE_HW_RENDER))
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET))
         bits |= AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT;
-    if (containsBits(usage0, GRALLOC_USAGE_HW_VIDEO_ENCODER))
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER))
+        bits |= AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER;
+    if (containsBits(consumerUsage, GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER))
         bits |= AHARDWAREBUFFER_USAGE0_VIDEO_ENCODE;
-    if (containsBits(usage0, GRALLOC_USAGE_PROTECTED))
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_PROTECTED))
         bits |= AHARDWAREBUFFER_USAGE0_PROTECTED_CONTENT;
+    if (containsBits(producerUsage, GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA))
+        bits |= AHARDWAREBUFFER_USAGE0_SENSOR_DIRECT_DATA;
 
     return bits;
 }
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index b2dee06..8590ecf 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -382,7 +382,7 @@
     s = nullptr;
 
     hidl_string tmp;
-    tmp.setToExternal(static_cast<const char *>(subBlob->data()), size);
+    tmp.setToExternal(static_cast<const char *>(subBlob->data()), size - 1);
 
     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
     blob->write(offset, &tmp, sizeof(tmp));
diff --git a/core/jni/android_os_seccomp.cpp b/core/jni/android_os_seccomp.cpp
index 2fe5d39..02c0c62 100644
--- a/core/jni/android_os_seccomp.cpp
+++ b/core/jni/android_os_seccomp.cpp
@@ -147,6 +147,9 @@
     // Needed for kernel to restart syscalls
     AllowSyscall(f, 128); // __NR_restart_syscall
 
+    // b/35034743
+    AllowSyscall(f, 267); // __NR_fstatfs64
+
     Trap(f);
 
     if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
@@ -209,6 +212,10 @@
     // b/34908783
     AllowSyscall(f, 250); // __NR_epoll_create
 
+    // b/34979910
+    AllowSyscall(f, 8);   // __NR_creat
+    AllowSyscall(f, 10);  // __NR_unlink
+
     Trap(f);
 
     return install_filter(f);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 5c65241..e2fc444 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -247,24 +247,42 @@
 
 static void DropCapabilitiesBoundingSet(JNIEnv* env) {
   for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
-    // Keep CAP_SYS_PTRACE in our bounding set so crash_dump can gain it.
-    if (i == CAP_SYS_PTRACE) {
-      continue;
-    }
-
     int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
     if (rc == -1) {
       if (errno == EINVAL) {
         ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
               "your kernel is compiled with file capabilities support");
       } else {
+        ALOGE("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
         RuntimeAbort(env, __LINE__, "prctl(PR_CAPBSET_DROP) failed");
       }
     }
   }
 }
 
-static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+static void SetInheritable(JNIEnv* env, uint64_t inheritable) {
+  __user_cap_header_struct capheader;
+  memset(&capheader, 0, sizeof(capheader));
+  capheader.version = _LINUX_CAPABILITY_VERSION_3;
+  capheader.pid = 0;
+
+  __user_cap_data_struct capdata[2];
+  if (capget(&capheader, &capdata[0]) == -1) {
+    ALOGE("capget failed: %s", strerror(errno));
+    RuntimeAbort(env, __LINE__, "capget failed");
+  }
+
+  capdata[0].inheritable = inheritable;
+  capdata[1].inheritable = inheritable >> 32;
+
+  if (capset(&capheader, &capdata[0]) == -1) {
+    ALOGE("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
+    RuntimeAbort(env, __LINE__, "capset failed");
+  }
+}
+
+static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective,
+                            uint64_t inheritable) {
   __user_cap_header_struct capheader;
   memset(&capheader, 0, sizeof(capheader));
   capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -276,9 +294,12 @@
   capdata[1].effective = effective >> 32;
   capdata[0].permitted = permitted;
   capdata[1].permitted = permitted >> 32;
+  capdata[0].inheritable = inheritable;
+  capdata[1].inheritable = inheritable >> 32;
 
   if (capset(&capheader, &capdata[0]) == -1) {
-    ALOGE("capset(%" PRId64 ", %" PRId64 ") failed", permitted, effective);
+    ALOGE("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") failed: %s", permitted,
+          effective, inheritable, strerror(errno));
     RuntimeAbort(env, __LINE__, "capset failed");
   }
 }
@@ -532,6 +553,7 @@
       EnableKeepCapabilities(env);
     }
 
+    SetInheritable(env, permittedCapabilities);
     DropCapabilitiesBoundingSet(env);
 
     bool use_native_bridge = !is_system_server && (instructionSet != NULL)
@@ -604,7 +626,7 @@
         }
     }
 
-    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+    SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
 
     SetSchedulerPolicy(env);
 
diff --git a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
index 60e065c..a5d0596 100644
--- a/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
+++ b/core/jni/include/android_runtime/android_hardware_HardwareBuffer.h
@@ -40,12 +40,13 @@
       uint32_t format);
 
 /* Convert from AHARDWAREBUFFER_USAGE* flags to to gralloc usage flags. */
-extern uint32_t android_hardware_HardwareBuffer_convertToGrallocUsageBits(
-      uint64_t usage0, uint64_t usage1);
+extern void android_hardware_HardwareBuffer_convertToGrallocUsageBits(
+      uint64_t usage0, uint64_t usage1, uint64_t* outProducerUsage,
+      uint64_t* outConsumerUsage);
 
 /* Convert from gralloc usage flags to to AHARDWAREBUFFER_USAGE0* flags. */
 extern uint64_t android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
-      uint64_t usage0);
+      uint64_t producerUsage, uint64_t consumerUsage);
 
 } // namespace android
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 11eb47b..7b800b3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2365,6 +2365,11 @@
     <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by the CompanionDeviceManager to ensure that only the system can bind to it.
+         @hide -->
+    <permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
          that only the system can bind to it.
          @hide -->
@@ -3215,6 +3220,11 @@
     <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by system apps when accessing restricted VR APIs.
+         <p>Protection level: signature -->
+    <permission android:name="android.permission.RESTRICTED_VR_ACCESS"
+        android:protectionLevel="signature|preinstalled" />
+
     <!-- Required to make calls to {@link android.service.vr.IVrManager}.
          @hide -->
     <permission android:name="android.permission.ACCESS_VR_MANAGER"
diff --git a/core/res/res/drawable/btn_event_material.xml b/core/res/res/drawable/btn_event_material.xml
new file mode 100644
index 0000000..47c49cf
--- /dev/null
+++ b/core/res/res/drawable/btn_event_material.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+
+    <path
+        android:fillColor="#90ffffff"
+        android:pathData="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99 .9 -1.99 2L3 19c0 1.1 .89 2 2
+2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z" />
+    <path android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/btn_keyboard_key_material.xml b/core/res/res/drawable/btn_keyboard_key_material.xml
new file mode 100644
index 0000000..14a9492f
--- /dev/null
+++ b/core/res/res/drawable/btn_keyboard_key_material.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+
+    <path
+        android:fillColor="#90ffffff"
+        android:pathData="M20 5H4c-1.1 0-1.99 .9 -1.99 2L2 17c0 1.1 .9 2 2 2h16c1.1 0 2-.9
+2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0
+3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9
+7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z" />
+    <path
+        android:pathData="M0 0h24v24H0zm0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/values-ldrtl/dimens.xml b/core/res/res/drawable/resolver_icon_placeholder.xml
similarity index 69%
rename from core/res/res/values-ldrtl/dimens.xml
rename to core/res/res/drawable/resolver_icon_placeholder.xml
index 807c042..049cfee 100644
--- a/core/res/res/values-ldrtl/dimens.xml
+++ b/core/res/res/drawable/resolver_icon_placeholder.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<resources>
-    <item type="dimen" format="integer" name="time_picker_column_start_material">1</item>
-    <item type="dimen" format="integer" name="time_picker_column_end_material">0</item>
-</resources>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
+    <solid android:color="#10000000"/>
+    <size android:width="36dp" android:height="36dp"/>
+</shape>
\ No newline at end of file
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 70833d6..8b95f9f 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -15,28 +15,17 @@
      limitations under the License.
 -->
 
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layoutDirection="ltr">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
 
-    <!-- Provides a background for the time layout that extends into the button bar area. -->
-    <com.android.internal.widget.DrawingSpace
+    <LinearLayout
         android:id="@+id/time_header"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_column="@dimen/time_picker_column_start_material"
-        android:layout_row="0"
-        android:layout_rowSpan="3"
-        android:layout_gravity="center|fill"
-        android:layoutDirection="locale" />
-
-    <RelativeLayout
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_column="@dimen/time_picker_column_start_material"
-        android:layout_row="1"
-        android:layout_gravity="center|fill"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center"
         android:paddingStart="?attr/dialogPreferredPadding"
         android:paddingEnd="?attr/dialogPreferredPadding">
 
@@ -44,10 +33,8 @@
             android:id="@+id/time_layout"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:layout_centerInParent="true"
             android:paddingTop="@dimen/timepicker_radial_picker_top_margin"
-            android:layout_marginBottom="-12dp">
+            android:orientation="horizontal">
 
             <!-- The hour should always be to the left of the separator,
                  regardless of the current locale's layout direction. -->
@@ -125,38 +112,71 @@
                 android:includeFontPadding="false"
                 android:button="@null" />
         </RadioGroup>
-    </RelativeLayout>
+    </LinearLayout>
 
-    <ViewStub
-        android:id="@id/topPanel"
-        android:layout="@layout/alert_dialog_title_material"
+    <TextView
+        android:visibility="gone"
+        android:id="@+id/input_header"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:paddingStart="@dimen/dialog_padding_material"
+        android:paddingEnd="@dimen/dialog_padding_material"
+        android:paddingTop="20dp"
+        android:paddingBottom="20dp"
+        android:includeFontPadding="false"
+        android:textAppearance="@style/TextAppearance.Material.TimePicker.InputHeader"
+        android:text="@string/time_picker_header_text"/>
+
+    <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_column="@dimen/time_picker_column_end_material"
-        android:layout_row="0"
-        android:layout_gravity="top|fill_horizontal"
-        android:layoutDirection="locale" />
+        android:orientation="vertical">
 
-    <android.widget.RadialTimePickerView
-        android:id="@+id/radial_picker"
-        android:layout_width="@dimen/timepicker_radial_picker_dimen"
-        android:layout_height="@dimen/timepicker_radial_picker_dimen"
-        android:layout_column="@dimen/time_picker_column_end_material"
-        android:layout_row="1"
-        android:layout_rowWeight="1"
-        android:layout_gravity="center|fill"
-        android:layout_marginTop="@dimen/timepicker_radial_picker_top_margin"
-        android:layout_marginStart="@dimen/timepicker_radial_picker_horizontal_margin"
-        android:layout_marginEnd="@dimen/timepicker_radial_picker_horizontal_margin"
-        android:layoutDirection="locale" />
+        <android.widget.RadialTimePickerView
+            android:id="@+id/radial_picker"
+            android:layout_width="@dimen/timepicker_radial_picker_dimen"
+            android:layout_height="@dimen/timepicker_radial_picker_dimen"
+            android:layout_gravity="center|fill"
+            android:layout_marginTop="@dimen/timepicker_radial_picker_top_margin"
+            android:layout_marginStart="@dimen/timepicker_radial_picker_horizontal_margin"
+            android:layout_marginEnd="@dimen/timepicker_radial_picker_horizontal_margin"
+            android:layoutDirection="locale" />
 
-    <ViewStub
-        android:id="@id/buttonPanel"
-        android:layout="@layout/alert_dialog_button_bar_material"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_column="@dimen/time_picker_column_end_material"
-        android:layout_row="2"
-        android:layout_gravity="bottom|fill_horizontal"
-        android:layoutDirection="locale" />
-</GridLayout>
+        <android.widget.TextInputTimePickerView
+            android:id="@+id/input_mode"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingStart="?attr/dialogPreferredPadding"
+            android:paddingEnd="?attr/dialogPreferredPadding"
+            android:visibility="gone" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <ImageButton
+                android:id="@+id/toggle_mode"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:layout_marginStart="12dp"
+                android:layout_marginEnd="12dp"
+                android:padding="12dp"
+                android:background="?attr/selectableItemBackgroundBorderless"
+                android:tint="?attr/colorControlNormal"
+                android:src="@drawable/btn_keyboard_key_material"
+                android:contentDescription="@string/time_picker_text_input_mode_description" />
+            <Space
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
+            <ViewStub
+                android:id="@id/buttonPanel"
+                android:layout="@layout/alert_dialog_button_bar_material"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layoutDirection="locale" />
+        </LinearLayout>
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index d8dd447..7dee2af 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -53,8 +53,7 @@
                    android:visibility="gone"
                    android:scaleType="fitCenter"
                    android:layout_below="@id/profile_button"
-                   android:layout_alignParentLeft="true"
-                   />
+                   android:layout_alignParentLeft="true"/>
         <TextView android:id="@+id/title"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 02cd8cd..bed80ed 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -24,6 +24,7 @@
     android:layout_width="match_parent">
 
     <LinearLayout
+        android:id="@+id/prefs_container"
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="0px"
@@ -61,8 +62,7 @@
                 android:layout_width="0px"
                 android:layout_height="match_parent"
                 android:layout_weight="@integer/preferences_right_pane_weight"
-                android:orientation="vertical"
-                android:visibility="gone" >
+                android:orientation="vertical">
 
             <!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an
                 empty layout or just padding, and PreferenceActivity will put the breadcrumbs in
diff --git a/core/res/res/layout/preference_list_content_material.xml b/core/res/res/layout/preference_list_content_material.xml
index 1bc527e..37b4119 100644
--- a/core/res/res/layout/preference_list_content_material.xml
+++ b/core/res/res/layout/preference_list_content_material.xml
@@ -24,6 +24,7 @@
     android:layout_width="match_parent">
 
     <LinearLayout
+        android:id="@+id/prefs_container"
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="0px"
@@ -64,8 +65,7 @@
                 android:layout_width="0px"
                 android:layout_height="match_parent"
                 android:layout_weight="@integer/preferences_right_pane_weight"
-                android:orientation="vertical"
-                android:visibility="gone" >
+                android:orientation="vertical">
 
             <!-- Breadcrumb inserted here, in certain screen sizes. In others, it will be an
                 empty layout or just padding, and PreferenceActivity will put the breadcrumbs in
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 02dc2ed..8101183 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -45,6 +45,7 @@
                 android:layout_marginStart="16dp"
                 android:layout_marginEnd="16dp"
                 android:layout_marginTop="20dp"
+                android:src="@drawable/resolver_icon_placeholder"
                 android:scaleType="fitCenter" />
 
             <TextView
diff --git a/core/res/res/layout/time_picker_material.xml b/core/res/res/layout/time_picker_material.xml
index 37a7384..7597379 100644
--- a/core/res/res/layout/time_picker_material.xml
+++ b/core/res/res/layout/time_picker_material.xml
@@ -34,4 +34,53 @@
         android:layout_marginTop="@dimen/timepicker_radial_picker_top_margin"
         android:layout_marginStart="@dimen/timepicker_radial_picker_horizontal_margin"
         android:layout_marginEnd="@dimen/timepicker_radial_picker_horizontal_margin" />
+    <TextView
+        android:visibility="gone"
+        android:id="@+id/input_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="@dimen/dialog_padding_material"
+        android:paddingEnd="@dimen/dialog_padding_material"
+        android:paddingTop="20dp"
+        android:paddingBottom="20dp"
+        android:includeFontPadding="false"
+        android:fontFamily="sans-serif-medium"
+        android:textSize="34sp"
+        android:textColor="@color/white"
+        android:text="@string/time_picker_header_text"/>
+    <android.widget.TextInputTimePickerView
+        android:id="@+id/input_mode"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="?attr/dialogPreferredPadding"
+        android:paddingEnd="?attr/dialogPreferredPadding"
+        android:visibility="gone" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <ImageButton
+            android:id="@+id/toggle_mode"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_marginStart="12dp"
+            android:layout_marginEnd="12dp"
+            android:padding="12dp"
+            android:background="?attr/selectableItemBackgroundBorderless"
+            android:tint="?attr/colorControlNormal"
+            android:src="@drawable/btn_keyboard_key_material"
+            android:contentDescription="@string/time_picker_text_input_mode_description" />
+        <Space
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" />
+        <ViewStub
+            android:id="@id/buttonPanel"
+            android:layout="@layout/alert_dialog_button_bar_material"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layoutDirection="locale" />
+    </LinearLayout>
+
 </LinearLayout>
diff --git a/core/res/res/layout/time_picker_text_input_material.xml b/core/res/res/layout/time_picker_text_input_material.xml
new file mode 100644
index 0000000..f17b80e
--- /dev/null
+++ b/core/res/res/layout/time_picker_text_input_material.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <TextView
+        android:id="@+id/top_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="26dp"
+        android:layout_marginBottom="8dp"
+        android:text="@string/time_picker_prompt_label"
+        android:textAppearance="@style/TextAppearance.Material.TimePicker.PromptLabel" />
+
+    <RelativeLayout
+        android:id="@+id/input_block"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/top_label"
+        android:layoutDirection="ltr">
+        <EditText
+            android:id="@+id/input_hour"
+            android:layout_width="50dp"
+            android:layout_height="wrap_content"
+            android:inputType="number"
+            android:textAppearance="@style/TextAppearance.Material.TimePicker.InputField" />
+        <TextView
+            android:id="@+id/label_hour"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/input_hour"
+            android:layout_alignStart="@id/input_hour"
+            android:text="@string/time_picker_hour_label"/>
+
+        <TextView
+            android:id="@+id/input_separator"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignEnd="@id/input_hour"
+            android:layout_alignBaseline="@id/input_hour"
+            android:textAppearance="@style/TextAppearance.Material.TimePicker.InputField" />
+
+        <EditText
+            android:id="@+id/input_minute"
+            android:layout_width="50dp"
+            android:layout_height="wrap_content"
+            android:layout_alignBaseline="@id/input_hour"
+            android:layout_toEndOf="@id/input_separator"
+            android:inputType="number"
+            android:textAppearance="@style/TextAppearance.Material.TimePicker.InputField" />
+        <TextView
+            android:id="@+id/label_minute"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/input_minute"
+            android:layout_alignStart="@id/input_minute"
+            android:text="@string/time_picker_minute_label"/>
+
+        <TextView
+            android:visibility="invisible"
+            android:id="@+id/label_error"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/input_hour"
+            android:layout_alignStart="@id/input_hour"
+            android:textColor="?attr/textColorError"
+            android:text="@string/time_picker_input_error" />
+    </RelativeLayout>
+    <Spinner
+        android:id="@+id/am_pm_spinner"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBaseline="@id/input_block"
+        android:layout_alignParentEnd="true"/>
+
+</merge>
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 9be3635..46d0745 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Beheer die vertoonskerm se zoemvlak en posisionering."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Voer gebare uit"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan tik, swiep, knyp en ander gebare uitvoer."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Vingerafdrukgebare"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan gebare wat op die toestel se vingerafdruksensor uitgevoer word, vasvang"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktiveer of verander statusbalk"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"wees die statusbalk"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tik vir meer opsies."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouter gekoppel"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tik om USB-ontfouting te deaktiveer."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Kies om USB-ontfouting te deaktiveer."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Neem tans foutverslag …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deel foutverslag?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deel tans foutverslag …"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Nuus en tydskrifte"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kaarte en navigasie"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktiwiteit"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Toestelberging"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 41dff04..45206873 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"የማሳያውን የማጉያ ደረጃ እና አቀማመጥ ይቆጣጠሩ።"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"የጣት ምልክቶችን ያከናውኑ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"መታ ማድረግ፣ ማንሸራተት፣ መቆንጠጥ እና ሌሎች የጣት ምልክቶችን ማከናወን ይችላል።"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"የጣት አሻራ ምልክቶች"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"በመሣሪያዎቹ የጣት አሻራ ዳሳሽ ላይ የተከናወኑ የጣት ምልክቶችን መያዝ ይችላል።"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"የሁኔታ አሞሌ መሆን"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"ለተጨማሪ አማራጮች መታ ያድርጉ።"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB አድስ ተያይዟል"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"የዩኤስቢ ማረሚያን ለማሰናከል መታ ያድርጉ።"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB ማረሚያ ላለማንቃት ምረጥ።"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"የሳንካ ሪፖርትን በመውሰድ ላይ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"የሳንካ ሪፖርት ይጋራ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"የሳንካ ሪፖርትን በማጋራት ላይ…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ዜና እና መጽሔቶች"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"ካርታዎች እና ዳሰሳ"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ውጤታማነት"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"የመሣሪያ ማከማቻ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 07e1699..95118c2 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -290,6 +290,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"يمكنك التحكم في مستوى التكبير/التصغير للشاشة وتحديد الموضع."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"تنفيذ إيماءات"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"يمكن النقر والتمرير بسرعة والتصغير وتنفيذ إيماءات أخرى."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"إيماءات بصمات الإصبع"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"يمكن أن تلتقط الإيماءات التي تم تنفيذها على مستشعر بصمات الإصبع في الأجهزة."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"تعطيل شريط الحالة أو تعديله"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"للسماح للتطبيق بتعطيل شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"العمل كشريط للحالة"</string>
@@ -1226,6 +1228,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"انقر للحصول على المزيد من الخيارات."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏تم توصيل تصحيح أخطاء USB"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"‏انقر لتعطيل تصحيح أخطاء USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"‏اختيار تعطيل تصحيح أخطاء USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"جارٍ الحصول على تقرير الخطأ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"هل تريد مشاركة تقرير الخطأ؟"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"جارٍ مشاركة تقرير الخطأ…"</string>
@@ -1813,4 +1816,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"الأخبار والمجلات"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"الخرائط والتنقل"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"الإنتاجية"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"السعة التخزينية للجهاز"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index ebc4eed..cf377b2 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekran yaxınlaşdırma səviyyəsi və yerləşdirməsinə nəzarət edin."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Jestlər ilə əməliyyat aparın"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Digər jestlərə tıklaya, sürüşdürə və əməliyyat apara bilərsiniz."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Barmaq izi işarələri"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Cihazların barmaq izi sensorunda olan işarələri əldə edə bilər"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"status panelini deaktivləşdir və ya dəyişdir"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"status paneli edin"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Əlavə seçimlər üçün tıklayın."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB sazlama qoşuludur"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB debaqı deaktivasiya etmək üçün tıklayın."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USb debaqı deaktivasiya etməyi seçin."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabatı verilir..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Baq hesabatı paylaşılır..."</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Xəbər və Jurnallar"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Xəritə və Naviqasiya"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Məhsuldarlıq"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Cihaz yaddaşı"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 810ed0f..e56d938 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -281,6 +281,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Upravlja nivoom zumiranja prikaza i određivanjem položaja."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Obavljanje pokreta"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može da dodiruje, lista, skuplja prikaz i obavlja druge pokrete."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pokreti za otisak prsta"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Može da registruje pokrete na senzoru za otisak prsta na uređaju."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmena statusne trake"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"funkcionisanje kao statusna traka"</string>
@@ -1166,6 +1168,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za još opcija."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka sa USB-a je uspostavljeno"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da biste onemogućili otklanjanje grešaka sa USB-a."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Izaberite da biste onemogućili otklanjanja grešaka sa USB-a."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izveštaj o grešci se generiše…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li da podelite izveštaj o grešci?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deli se izveštaj o grešci…"</string>
@@ -1720,4 +1723,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Novosti i časopisi"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mape i navigacija"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivnost"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Memorijski prostor uređaja"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 7ad40c4..6383c39 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Кіраваць маштабам дысплэя і пазіцыянаваннем."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Выконваць жэсты"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна кранаць, праводзіць пальцам, маштабаваць шчыпком, а таксама выконваць іншыя жэсты."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жэсты адбіткаў пальцаў"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Можа распазнаваць жэсты на сканеры адбіткаў пальцаў прылады."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"адключаць ці змяняць радок стану"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Дазваляе прыкладанням адключаць радок стану або дадаваць і выдаляць сістэмныя значкі."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"быць панэллю стану"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Дакраніцеся, каб атрымаць іншыя параметры."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Адладка па USB падключана"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Дакраніцеся, каб адключыць адладку па USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Выберыце, каб адключыць адладку USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Стварэнне справаздачы пра памылку…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Падзяліцца справаздачай пра памылку?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Перадача справаздачы пра памылку..."</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Навіны і часопісы"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карты і навігацыя"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Прадукцыйнасць"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Сховішча на прыладзе"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9afed47..1238e2c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управление на нивото на мащаба и позиционирането на дисплея."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Извършване на жестове"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можете да докосвате, да прекарвате пръст, да събирате пръсти и да извършвате други жестове."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жестове за отпечатък"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Може да улавя жестовете, извършени върху сензора за отпечатъци на устройството."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"деактивиране или промяна на лентата на състоянието"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"изпълняване на ролята на лента на състоянието"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Докоснете за още опции."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отстраняване на грешки през USB"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Докоснете, за да деактивирате отстраняването на грешки през USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Изберете, за да деактивирате отстраняването на грешки през USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Сигналът за програмна грешка се извлича…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели ли сигналът за програмна грешка?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Сигналът за програмна грешка се споделя…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Новини и списания"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карти и навигация"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Производителност"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Хранилище на устройството"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 6522537..9bedf58 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -63,8 +63,8 @@
     <string name="needPuk2" msgid="4526033371987193070">"সিম কার্ড অবরোধ মুক্ত করতে PUK2 লিখুন৷"</string>
     <string name="enablePin" msgid="209412020907207950">"অসফল, সিম/RUIM লক সক্ষম করুন৷"</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
-      <item quantity="one">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM লক হয়ে যাবে৷</item>
-      <item quantity="other">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM লক হয়ে যাবে৷</item>
+      <item quantity="one">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম লক হয়ে যাবে৷</item>
+      <item quantity="other">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম লক হয়ে যাবে৷</item>
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -255,7 +255,7 @@
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"ক্যালেন্ডার"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"আপনার ক্যালেন্ডারে অ্যাক্সেস"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS বার্তাগুলি পাঠাতে এবং দেখতে"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"এসএমএসগুলি পাঠাতে এবং দেখতে"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"সঞ্চয়স্থান"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"আপনার ডিভাইসে ফটো, মিডিয়া এবং ফাইলগুলিতে অ্যাক্সেস"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্রোফোন"</string>
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"প্রদর্শনের জুমের স্তর এবং অবস্থান নির্ধারন নিয়ন্ত্রণ করুন৷"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"অঙ্গভঙ্গির কাজগুলি সম্পাদন করুন"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য অঙ্গভঙ্গির কাজগুলি সম্পাদন করতে পারবেন৷"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ফিঙ্গারপ্রিন্ট সেন্সরের উপর করা অঙ্গভঙ্গিগুলি"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ডিভাইসের ফিঙ্গারপ্রিন্ট সেন্সরের উপর আঙ্গুলের অঙ্গভঙ্গি ক্যাপচার করতে পারে।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"স্থিতি দন্ড নিষ্ক্রিয় অথবা সংশোধন করে"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"অ্যাপ্লিকেশানকে স্থিতি দন্ড অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"স্থিতি দন্ডে থাকুন"</string>
@@ -291,7 +293,7 @@
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"আউটগোয়িং কলগুলি পুনঃচালিত করুন"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"অ্যাপ্লিকেশানকে কল চলাকালীন অন্য একটি নম্বরে কল পুনঃনির্দেশ বা কলটি একসথে বন্ধ করার সাথে ডায়াল করা নম্বরটি দেখতে দেয়৷"</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"পাঠ্য বার্তা পান (SMS)"</string>
-    <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে SMS বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
+    <string name="permdesc_receiveSms" msgid="6424387754228766939">"অ্যাপ্লিকেশানটিকে এসএমএস প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"পাঠ্য বার্তা পান (MMS)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"অ্যাপ্লিকেশানটিকে MMS বার্তা প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো বার্তাগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"সেল সম্প্রচার বার্তা পড়ুন"</string>
@@ -299,7 +301,7 @@
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"গ্রাহক হিসাবে নেওয়া ফিডগুলি পড়ে"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"অ্যাপ্লিকেশানকে বর্তমানে সিঙ্ক করা ফিডগুলির সম্পর্কে বিবরণ পেতে দেয়৷"</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMS পাঠানো ও দেখা,আপনি কি পরিচিতি কে এগুলি করার অনুমতি দেবেন?"</string>
-    <string name="permdesc_sendSms" msgid="7094729298204937667">"অ্যাপ্লিকেশানটিকে SMS বার্তাগুলি পাঠাতে অনুমতি দেয়৷ এর জন্য অপ্রত্যাশিত চার্জ কাটা হতে পারে৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার নিশ্চিতকরণ ছাড়া বার্তা পাঠানোর মাধ্যমে আপনাকে অর্থ চার্জ করতে পারে৷"</string>
+    <string name="permdesc_sendSms" msgid="7094729298204937667">"অ্যাপ্লিকেশানটিকে এসএমএসগুলি পাঠাতে অনুমতি দেয়৷ এর জন্য অপ্রত্যাশিত চার্জ কাটা হতে পারে৷ ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার নিশ্চিতকরণ ছাড়া বার্তা পাঠানোর মাধ্যমে আপনাকে অর্থ চার্জ করতে পারে৷"</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"আপনার পাঠ্য বার্তা পড়ুন (SMS বা MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"এই অ্যাপটি আপনার ট্যাবলেটে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string>
     <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"এই অ্যাপটি আপনার টিভিতে সংরক্ষিত সমস্ত SMS (পাঠ্য) বার্তা পড়তে পারে৷"</string>
@@ -370,7 +372,7 @@
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ভলিউম এবং যেখানে স্পিকার আউটপুট সামগ্রী হিসাবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"অডিও রেকর্ড"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"এই অ্যাপটি মাইক্রোফোন ব্যবহার করে যে কোনো সময় অডিও রেকর্ড করতে পারে৷"</string>
-    <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM এ আদেশগুলি পাঠান"</string>
+    <string name="permlab_sim_communication" msgid="2935852302216852065">"সিম এ আদেশগুলি পাঠান"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"অ্যাপ্লিকেশানটিকে সিম কার্ডে কমান্ডগুলি পাঠানোর অনুমতি দেয়৷ এটি খুবই বিপজ্জনক৷"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ছবি এবং ভিডিও তোলে"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"এই অ্যাপটি যে কোনো সময় ক্যামেরা ব্যবহার করে ছবি তুলতে বা ভিডিও রেকর্ড করতে পারে৷"</string>
@@ -479,8 +481,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"অ্যাপ্লিকেশানকে SD কার্ডে লেখার অনুমতি দেয়৷"</string>
     <string name="permlab_use_sip" msgid="2052499390128979920">"SIP কল করুন/গ্রহণ করুন"</string>
     <string name="permdesc_use_sip" msgid="2297804849860225257">"অ্যাপ্লিকেশানকে SIP কল করতে ও গ্রহণ করতে অনুমতি দেয়।"</string>
-    <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"নতুন টেলিকম SIM সংযোগগুলির নিবন্ধন"</string>
-    <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"অ্যাপ্লিকেশানটিকে নতুন টেলিকম SIM সংযোগগুলি নিবন্ধিত করতে অনুমোদিত করে৷"</string>
+    <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"নতুন টেলিকম সিম সংযোগগুলির নিবন্ধন"</string>
+    <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"অ্যাপ্লিকেশানটিকে নতুন টেলিকম সিম সংযোগগুলি নিবন্ধিত করতে অনুমোদিত করে৷"</string>
     <string name="permlab_register_call_provider" msgid="108102120289029841">"নতুন টেলিকম সংযোগগুলির নিবন্ধন"</string>
     <string name="permdesc_register_call_provider" msgid="7034310263521081388">"নতুন টেলিকম সংযোগ নিবন্ধিত করতে অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷"</string>
     <string name="permlab_connection_manager" msgid="1116193254522105375">"টেলিকম সংযোগগুলি পরিচালনা করুন"</string>
@@ -692,7 +694,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"মুখের সাহায্যে আনলক করার প্রচেষ্টা যতবার করা যায় তার সীমা পেরিয়ে গেছে"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"কোনো সিম কার্ড নেই"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ট্যাবলেটের মধ্যে কোনো সিম কার্ড নেই৷"</string>
-    <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"টিভির মধ্যে কোনো SIM কার্ড নেই৷"</string>
+    <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"টিভির মধ্যে কোনো সিম কার্ড নেই৷"</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ফোনের মধ্যে কোনো সিম কার্ড নেই৷"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"একটি সিম কার্ড ঢোকান৷"</string>
     <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"সিম কার্ডটি অনুপস্থিত বা পাঠযোগ্য নয়৷ একটি সিম কার্ড ঢোকান৷"</string>
@@ -1104,8 +1106,8 @@
     <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"আপনার টিভি <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এ সংযুক্ত থাকার সময় ওয়াই-ফাই থেকে সাময়িকভাবে সংযোগ বিচ্ছিন্ন হবে৷"</string>
     <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"ফোনটি যখন <xliff:g id="DEVICE_NAME">%1$s</xliff:g> এ সংযুক্ত হবে তখন এটি ওয়াই-ফাই থেকে সাময়িকভাবে সংযোগ বিচ্ছিন্ন হবে"</string>
     <string name="select_character" msgid="3365550120617701745">"অক্ষর ঢোকান"</string>
-    <string name="sms_control_title" msgid="7296612781128917719">"SMS বার্তা পাঠানো হচ্ছে"</string>
-    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অনেকগুলি SMS বার্তা পাঠাচ্ছে৷ আপনি কি এই অ্যাপ্লিকেশানটিকে বার্তা পাঠানো চালিয়ে যাওয়ার অনুমতি দিতে চান?"</string>
+    <string name="sms_control_title" msgid="7296612781128917719">"এসএমএস পাঠানো হচ্ছে"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অনেকগুলি এসএমএস পাঠাচ্ছে৷ আপনি কি এই অ্যাপ্লিকেশানটিকে বার্তা পাঠানো চালিয়ে যাওয়ার অনুমতি দিতে চান?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"অনুমতি দিন"</string>
     <string name="sms_control_no" msgid="625438561395534982">"আস্বীকার করুন"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt; এ একটি বার্তা পাঠাতে চায়৷"</string>
@@ -1123,10 +1125,10 @@
     <string name="sim_added_title" msgid="3719670512889674693">"সিম কার্ড যোগ করা হয়েছে"</string>
     <string name="sim_added_message" msgid="7797975656153714319">"সেলুলার নেটওয়ার্ক অ্যাক্সেস করতে আপনার ডিভাইস পুনর্সূচনা করুন"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"পুনর্সূচনা"</string>
-    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"যাতে আপনার নতুন SIM সঠিকভাবে কাজ করে, তার জন্য আপনাকে আপনার পরিষেবা প্রদানকারীর থেকে একটি অ্যাপ্লিকেশান ইনস্টল করতে এবং খুলতে হবে৷"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"যাতে আপনার নতুন সিম সঠিকভাবে কাজ করে, তার জন্য আপনাকে আপনার পরিষেবা প্রদানকারীর থেকে একটি অ্যাপ্লিকেশান ইনস্টল করতে এবং খুলতে হবে৷"</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"অ্যাপ্লিকেশানটি পান"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"এখনই নয়"</string>
-    <string name="carrier_app_notification_title" msgid="8921767385872554621">"নতুন SIM ঢোকানো হয়েছে"</string>
+    <string name="carrier_app_notification_title" msgid="8921767385872554621">"নতুন সিম ঢোকানো হয়েছে"</string>
     <string name="carrier_app_notification_text" msgid="1132487343346050225">"এটিকে সেট আপ করতে আলতো চাপুন"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"সময় সেট করুন"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"তারিখ সেট করুন"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"আরো বিকল্পের জন্য আলতো চাপুন৷"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ডিবাগিং সংযুক্ত হয়েছে"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ডিবাগিং অক্ষম করতে আলতো চাপুন৷"</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ত্রুটির প্রতিবেদন নেওয়া হচ্ছে..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ত্রুটির প্রতিবেদন শেয়ার করবেন?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ত্রুটির প্রতিবেদন শেয়ার করা হচ্ছে..."</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"খবর ও পত্রিকাগুলি"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"মানচিত্র ও নেভিগেশান"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"উৎপাদনশীলতা"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ডিভাইসের সঞ্চয়স্থান"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c6d70f3..66ef19a 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -281,6 +281,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolira stepen uvećanja prikaza na ekranu i podešavanje položaja."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Praviti pokrete"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može dodirivati, prevlačiti, hvatati prstima i praviti druge pokrete."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pokreti otiska prsta"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Moguće je zabilježiti pokrete na senzoru za otisak prsta uređaja."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili mijenjanje statusne trake"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Dozvoljava aplikaciji onemogućavanje statusne trake ili dodavanje i uklanjanje sistemskih ikona."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"funkcioniranje u vidu statusne trake"</string>
@@ -1168,6 +1170,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za više opcija."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Otklanjanje grešaka putem uređaja spojenog na USB je uspostavljeno"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da onemogućite otklanjanje grešaka putem uređaja spojenog na USB."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Prijem izvještaja o grešci..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Podijeliti izvještaj o grešci?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvještaja o grešci..."</string>
@@ -1722,4 +1726,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Vijesti i časopisi"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mape i navigacija"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivnost"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Memorija uređaja"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index eebe75f..b01f382 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el nivell i el posicionament del zoom de la pantalla."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Utilitza gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Pot tocar, lliscar, pessigar i utilitzar altres gestos."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos amb les empremtes digitals"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Captura gestos realitzats en el sensor d\'empremtes digitals del dispositiu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra d\'estat"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"aparèixer a la barra d\'estat"</string>
@@ -950,7 +952,7 @@
     <string name="inputMethod" msgid="1653630062304567879">"Mètode d\'introducció de text"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
     <string name="email" msgid="4560673117055050403">"Correu electrònic"</string>
-    <string name="dial" msgid="2275093056198652749">"Marcatge"</string>
+    <string name="dial" msgid="2275093056198652749">"Telèfon"</string>
     <string name="map" msgid="5441053548030107189">"Mapa"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"L\'espai d\'emmagatzematge s\'està esgotant"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"És possible que algunes funcions del sistema no funcionin"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Toca per veure més opcions."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració USB activada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Toca per desactivar la depuració USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecciona per desactivar la depuració USB"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"S\'està creant l\'informe d\'errors…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vols compartir l\'informe d\'errors?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"S\'està compartint l\'informe d\'errors…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Notícies i revistes"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapes i navegació"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivitat"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Emmagatzematge del dispositiu"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 68cc583..b8717d5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Určuje umístění a úroveň přiblížení displeje."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Provádění gest"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Může provádět gesta klepnutí, přejetí, stažení prstů a další."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesta otiskem prstu"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Dokáže rozpoznat gesta zadaná na snímači otisků prstů."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázání či změny stavového řádku"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"vydávání se za stavový řádek"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Klepnutím zobrazíte další možnosti."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladění přes USB připojeno"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Klepnutím zakážete ladění USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vyberte, chcete-li zakázat ladění USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Vytváření zprávy o chybě…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Sdílet zprávu o chybě?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sdílení zprávy o chybě…"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Zprávy a časopisy"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapy a navigace"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivita"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Úložiště zařízení"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f2b6be9..ebcd48e 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér skærmens zoomniveau og position."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Udfør bevægelser"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeraftryksbevægelser"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan registrere bevægelser, der foretages på enhedernes fingeraftrykslæser."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"vær statusbjælken"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tryk for at se flere muligheder."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-fejlretning er tilsluttet"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tryk for at deaktivere fejlretning via USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Vælg for at deaktivere USB-fejlretning."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Opretter fejlrapport…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele fejlrapporten?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler fejlrapport…"</string>
@@ -1395,7 +1398,7 @@
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Forkert pinkode"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Prøv igen om <xliff:g id="NUMBER">%1$d</xliff:g> sekunder."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Tegn dit mønster"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM-kort"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Indtast pinkode"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"Angiv adgangskode"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM-kortet er nu deaktiveret. Indtast PUK-koden for at fortsætte. Kontakt mobiloperatøren for at få flere oplysninger."</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Aviser og blade"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kort og navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Lagerplads på enheden"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5ba5464..7e31748 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Legt die Zoom-Stufe des Displays und die Zoom-Position auf dem Display fest."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Bewegungen möglich"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Tippen, Wischen, Zusammenziehen und andere Bewegungen möglich."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Bewegungen auf dem Fingerabdrucksensor"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Erfasst Bewegungen auf dem Fingerabdrucksensor des Geräts."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"Statusleiste darstellen"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Für weitere Optionen tippen."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging aktiviert"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Zum Deaktivieren von USB-Debugging tippen."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB-Debugging deaktivieren: auswählen"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird abgerufen…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Fehlerbericht wird geteilt…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Nachrichten &amp; Zeitschriften"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Karten &amp; Navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Effizienz"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Gerätespeicher"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 409b573..7458e04 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ελέγξτε το επίπεδο ζουμ και τη θέση της οθόνης."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Εκτέλεση κινήσεων"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Κινήσεις δακτυλικών αποτυπωμάτων"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Μπορεί να αναγνωρίσει κινήσεις που εκτελούνται στον αισθητήρα δακτυλικών αποτυπωμάτων των συσκευών."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποιεί ή να τροποποιεί την γραμμή κατάστασης"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ορίζεται ως γραμμή κατάστασης"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Πατήστε για περισσότερες επιλογές."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Συνδέθηκε ο εντοπισμός σφαλμάτων USB"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Πατήστε για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Επιλογή για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Λήψη αναφοράς σφάλματος…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Κοινή χρήση αναφοράς σφάλματος;"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Κοινή χρήση αναφοράς σφάλματος…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Ειδήσεις και περιοδικά"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Χάρτες και πλοήγηση"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Παραγωγικότητα"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Αποθηκευτικός χώρος συσκευής"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 02860cf..107f247 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerprint gestures"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Can capture gestures performed on the devices fingerprint sensor."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tap for more options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tap to disable USB debugging."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Select to disable USB debugging."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"News &amp; Magazines"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Maps &amp; Navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Device storage"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 02860cf..107f247 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerprint gestures"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Can capture gestures performed on the devices fingerprint sensor."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tap for more options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tap to disable USB debugging."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Select to disable USB debugging."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"News &amp; Magazines"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Maps &amp; Navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Device storage"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 02860cf..107f247 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerprint gestures"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Can capture gestures performed on the devices fingerprint sensor."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tap for more options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tap to disable USB debugging."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Select to disable USB debugging."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Taking bug report…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Share bug report?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Sharing bug report…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"News &amp; Magazines"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Maps &amp; Navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Device storage"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index bd3ac31..2749b35 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Usar gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permite presionar, deslizar, pellizcar y usar otros gestos."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos del sensor de huellas digitales"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Captura los gestos que se hacen en el sensor de huellas digitales de los dispositivos."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"aparecer en la barra de estado"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Presiona para ver más opciones."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración por USB conectada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Presiona para inhabilitar la depuración por USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccionar para desactivar la depuración por USB"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Realizando un informe de errores…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Noticias y revistas"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapas y navegación"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productividad"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Almacenamiento del dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 26f6005..bdb1381 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Puedes tocar y pellizcar la pantalla, deslizar el dedo y hacer otros gestos."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de huellas digitales"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Puede capturar los gestos realizados en el sensor de huellas digitales del dispositivo."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"inhabilitar o modificar la barra de estado"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"aparecer en la barra de estado"</string>
@@ -949,12 +951,9 @@
     <string name="deleteText" msgid="6979668428458199034">"Eliminar"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Método de introducción de texto"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"Acciones de texto"</string>
-    <!-- no translation found for email (4560673117055050403) -->
-    <skip />
-    <!-- no translation found for dial (2275093056198652749) -->
-    <skip />
-    <!-- no translation found for map (5441053548030107189) -->
-    <skip />
+    <string name="email" msgid="4560673117055050403">"Correo electrónico"</string>
+    <string name="dial" msgid="2275093056198652749">"Marcar"</string>
+    <string name="map" msgid="5441053548030107189">"Mapa"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Queda poco espacio"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Es posible que algunas funciones del sistema no funcionen."</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"No hay espacio suficiente para el sistema. Comprueba que haya 250 MB libres y reinicia el dispositivo."</string>
@@ -1149,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Toca para ver más opciones."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB habilitada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Toca para inhabilitar la depuración USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccionar para inhabilitar la depuración USB"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de errores…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"¿Compartir informe de errores?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartiendo informe de errores…"</string>
@@ -1205,10 +1205,8 @@
     <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que una aplicación consulte sesiones de instalación para ver detalles sobre instalaciones de paquetes activos."</string>
     <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
     <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a una aplicación solicitar la instalación de paquetes."</string>
-    <!-- no translation found for permlab_requestDeletePackages (1703686454657781242) -->
-    <skip />
-    <!-- no translation found for permdesc_requestDeletePackages (3406172963097595270) -->
-    <skip />
+    <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"solicitar eliminación de paquetes"</string>
+    <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"Permite a una aplicación solicitar la eliminación de paquetes."</string>
     <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"solicitar permiso para ignorar las optimizaciones de la batería"</string>
     <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permite que una aplicación solicite permiso para ignorar las optimizaciones de la batería."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Da dos toques para acceder al control de zoom."</string>
@@ -1694,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Noticias y revistas"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapas y navegación"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productividad"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Almacenamiento del dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 30e73d8..5b532b4 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Saate juhtida ekraani suumitaset ja asendit."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Liigutuste tegemine"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Saate puudutada, pühkida, sõrmi kokku-lahku liigutada ja teisi liigutusi teha."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Sõrmejälje liigutused"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Teil on võimalik jäädvustada liigutused, mis on tehtud seadmete sõrmejäljeanduri abil."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"keela või muuda olekuriba"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"olekuribana kuvamine"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Puudutage lisavalikute nägemiseks."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-silumine ühendatud"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Puudutage USB-silumise keelamiseks."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Valige USB silumise keelamiseks"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Veaaruande võtmine …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kas jagada veaaruannet?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Veaaruande jagamine …"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Uudised ja ajakirjad"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kaardid ja navigeerimine"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktiivsus"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Seadme salvestusruum"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index a49f94f..afb0a9c 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolatu pantailaren zoom-maila eta kokapena."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Keinuak egin"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Sakatu, lerratu, atximurkatu eta beste hainbat keinu egin ditzake."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Hatz-marken keinuak"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Gailuaren hatz-marken sentsorean egindako keinuak antzeman ditzake."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Desgaitu edo aldatu egoera-barra"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"Bihurtu egoera-barra"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Sakatu aukera gehiago ikusteko."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB arazketa konektatuta"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Sakatu USB arazketa desgaitzeko."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Akatsen txostena sortzen…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Akatsen txostena partekatu nahi duzu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Akatsen txostena partekatzen…"</string>
@@ -1232,7 +1236,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Horma-papera"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Aldatu horma-papera"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Jakinarazpenak hautemateko zerbitzua"</string>
-    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Errealitate birtualeko hautemailea"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"EB hautemailea"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Baldintza-hornitzailea"</string>
     <string name="notification_ranker_binding_label" msgid="774540592299064747">"Jakinarazpenen sailkapen-zerbitzua"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN eginbidea aktibatuta"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Albisteak eta aldizkariak"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapak eta nabigazioa"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktibitatea"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Gailuaren memoria"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3880caa..1e1c8fa 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"سطح و موقعیت بزرگ‌نمایی نمایشگر را کنترل کنید."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"اجرای اشاره‌ها"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"می‌توانید ضربه بزنید، انگشتتان را تند بکشید، انگشتانتان را به هم نزدیک یا از هم دور کنید و اشاره‌های دیگری اجرا کنید."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"اشاره‌های اثر انگشت"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"می‌تواند اشاره‌های انجام‌شده روی حسگر اثرانگشت دستگاه‌ها را ثبت کند."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"‏به برنامه اجازه می‎دهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"نوار وضعیت باشد"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"برای گزینه‌های بیشتر ضربه بزنید."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏اشکال‌زدایی USB متصل شد"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"‏برای غیرفعال کردن اشکال‌زدایی USB ضربه بزنید."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"‏انتخاب کنید تا رفع عیب USB غیرفعال شود."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"درحال گرفتن گزارش اشکال…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"گزارش اشکال به اشتراک گذاشته شود؟"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"درحال اشتراک‌گذاری گزارش اشکال…‏"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"اخبار و مجله"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"نقشه و پیمایش"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"بهره‌وری"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"حافظه دستگاه"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f0afbc8..c3c2c65 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Hallinnoi näytön zoomaustasoa ja asettelua."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Eleiden käyttäminen"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Lupa napauttaa, pyyhkäistä, nipistää ja käyttää muita eleitä."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Sormenjälkieleet"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Voi tallentaa laitteen sormenjälkitunnistimella tehtyjä eleitä."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"sijaita tilapalkissa"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Näet lisää vaihtoehtoja napauttamalla."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-vianetsintä yhdistetty"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Poista USB-vianetsintä käytöstä napauttamalla."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Poista USB-vianetsintä käytöstä valitsemalla tämä."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Luodaan virheraporttia…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Jaetaanko virheraportti?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Jaetaan virheraporttia…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Uutiset ja lehdet"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kartat ja navigointi"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Tuottavuus"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Laitteen tallennustila"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 65609f4..7e051c9 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Contrôler le niveau de zoom et le positionnement de l\'écran."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Effectuer des gestes"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Peut toucher, balayer, pincer et effectuer d\'autres gestes."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestes sur le capteur d\'empreintes digitales"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Peut capturer des gestes effectués sur le capteur d\'empreintes digitales des appareils."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"désactiver ou modifier la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"servir de barre d\'état"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Touchez pour afficher plus d\'options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB connecté"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Touchez pour désactiver le débogage USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Sélectionnez cette option pour désactiver le débogage USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création d\'un rapport de bogue en cours..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bogue?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bogue en cours..."</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Actualités et magazines"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Cartes et navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivité"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Mémoire de l\'appareil"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 66fb5b4..b8fcf28 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Contrôler le niveau de zoom et le positionnement de l\'écran"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Effectuer des gestes"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permet d\'appuyer sur l\'écran, de le balayer, de le pincer et d\'effectuer d\'autres gestes."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestes avec l\'empreinte digitale"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Peut enregistrer des gestes effectués sur le lecteur d\'empreinte digitale de l\'appareil."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Désactivation ou modification de la barre d\'état"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"remplacer la barre d\'état"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Appuyez ici pour plus d\'options."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Débogage USB activé"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Appuyez ici pour désactiver le débogage USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Sélectionnez cette option pour désactiver le débogage USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Création du rapport de bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Partager le rapport de bug ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Partage du rapport de bug…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Actualités et magazines"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Plans et navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivité"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Mémoire de l\'appareil"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 9b335a1..5d316f6 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o nivel do zoom e o posicionamento da pantalla"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar xestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Podes tocar, pasar o dedo, beliscar e realizar outros xestos."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Xestos de impresión dixital"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode rexistrar os xestos realizados no sensor de impresión dixital dos dispositivos."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar ou modificar a barra de estado"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite á aplicación desactivar a barra de estado ou engadir e eliminar as iconas do sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"actuar como a barra de estado"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Toca para ver máis opcións."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuración USB conectada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Toca para desactivar a depuración de erros de USB."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Creando informe de erros…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Queres compartir o informe de erros?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartindo informe de erros..."</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Noticias e revistas"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegación"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Almacenamento do dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 2bd3e41..b5c243b 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"પ્રદર્શનનું ઝૂમ સ્તર અને સ્થિતિનિર્ધારણ નિયંત્રિત કરો."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"હાવભાવ કરો"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ટૅપ, સ્વાઇપ, પિંચ કરી અને અન્ય હાવભાવ કરી શકે છે."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ફિંગરપ્રિન્ટ હાવભાવો"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ઉપકરણોનાં ફિંગરપ્રિન્ટ સેન્સર પર ભજવેલા હાવભાવ કૅપ્ચર કરી શકે છે."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"સ્થિતિ બાર અક્ષમ કરો અથવા સંશોધિત કરો"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"એપ્લિકેશનને સ્થિતિ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"સ્થિતિ બાર થાઓ"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"વધુ વિકલ્પો માટે ટૅપ કરો."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ડીબગિંગ કનેક્ટ થયું."</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ડીબગિંગ અક્ષમ કરવા માટે ટૅપ કરો."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"બગ રિપોર્ટ લઈ રહ્યાં છે…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"બગ રિપોર્ટ શેર કરીએ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"બગ રિપોર્ટ શેર કરી રહ્યાં છે…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"સમાચાર અને સામાયિકો"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"નકશા અને નેવિગેશન"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ઉત્પાદકતા"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ઉપકરણ સ્ટૉરેજ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 6300703..f2c3d43 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शन का ज़ूम स्‍तर और स्‍थिति निर्धारण नियंत्रित करें."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"हावभाव निष्पादित करें"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"इस सेवा के द्वारा टैप किया जा सकता है, स्वाइप किया जा सकता है, पिंच किया जा सकता है और अन्य हावभाव निष्पादित किए जा सकते हैं."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फ़िंगरप्रिंट हावभाव"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"डिवाइस फ़िंगरप्रिंट सेंसर पर किए गए हावभाव कैप्चर किए जा सकते हैं."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"स्‍थिति बार अक्षम या बदलें"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ऐप्स  को स्थिति बार अक्षम करने या सिस्‍टम आइकन को जोड़ने या निकालने देता है."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"स्‍थिति बार होने दें"</string>
@@ -951,7 +953,7 @@
     <string name="editTextMenuTitle" msgid="4909135564941815494">"लेख क्रियाएं"</string>
     <string name="email" msgid="4560673117055050403">"ईमेल करें"</string>
     <string name="dial" msgid="2275093056198652749">"डायल करें"</string>
-    <string name="map" msgid="5441053548030107189">"नक्शा"</string>
+    <string name="map" msgid="5441053548030107189">"मानचित्र"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"मेमोरी स्‍थान समाप्‍त हो रहा है"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"हो सकता है कुछ सिस्टम फ़ंक्शन कार्य न करें"</string>
     <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"सिस्टम के लिए पर्याप्त मेमोरी नहीं है. सुनिश्चित करें कि आपके पास 250MB का खाली स्थान है और फिर से प्रारंभ करें."</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"अधिक विकल्पों के लिए टैप करें."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग कनेक्ट किया गया"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB डीबग करना अक्षम करने के लिए टैप करें."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डीबग करना अक्षम करने के लिए चुनें."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट प्राप्त की जा रही है…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्ट साझा करें?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्ट साझा की जा रही है…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"समाचार और पत्रिकाएं"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"मानचित्र और मार्गदर्शक"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"उत्पादकता"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"डिवाइस में जगह"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index ee3ab30..11864c6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -281,6 +281,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolira razinu zumiranja i položaj zaslona."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Izvođenje pokreta"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može dodirnuti, prijeći prstom, spojiti prste i izvoditi druge pokrete."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pokreti za otisak prsta"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Može snimati pokrete izvršene na senzoru otiska prsta na uređaju."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmjena trake statusa"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"biti traka statusa"</string>
@@ -1166,6 +1168,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Dodirnite za više opcija."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Priključen je alat za otklanjanje pogrešaka USB-om"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Dodirnite da biste onemogućili otklanjanje pogrešaka putem USB-a."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Odaberite da biste onemogućili rješavanje programske pogreške na USB-u."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izrada izvješća o programskoj pogrešci…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li podijeliti izvješće o programskoj pogrešci?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvješća o programskoj pogrešci…"</string>
@@ -1720,4 +1723,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Vijesti i časopisi"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Karte i navigacija"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivnost"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Pohrana na uređaju"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 943dbc0..4c6d440 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"A kijelző nagyítási/kicsinyítési szintjének és pozíciójának vezérlése"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Kézmozdulatok végrehajtása"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Koppintás, ujjak gyors csúsztatása és összehúzása, illetve egyéb kézmozdulatok végrehajtása."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Kézmozdulatok az ujjlenyomat-érzékelőn"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Érzékeli az ujjlenyomat-érzékelőn végzett kézmozdulatokat."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"állapotsor kikapcsolása vagy módosítása"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"az állapotsor szerepének átvétele"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Koppintson a további beállítások megjelenítéséhez."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hibakereső csatlakoztatva"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Koppintson az USB fejlesztő mód kikapcsolásához."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Válassza ezt az USB hibakeresés kikapcsolásához."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hibajelentés készítése…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Megosztja a hibajelentést?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hibajelentés megosztása…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Hírlapok és folyóiratok"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Térképek és navigáció"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Irodai alkalmazások"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Eszköztárhely"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 7c579d1..276a326 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ցուցասարքի մասշտաբավորման և դիրքավորման կառավարում:"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Կատարել ժեստեր"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Կարող է հպել, թերթել, պտղունցել և կատարել այլ ժեստեր:"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Մատնահետքերի սկաների ժեստեր"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Կարող է նկարահանել մատնահետքերի սկաների վրա կատարվող ժեստերը"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"լինել կարգավիճակի գոտի"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Հպեք՝ լրացուցիչ ընտրանքների համար:"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB վրիպազերծումը միացված է"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Հպեք՝ USB վրիպազերծումն անջատելու համար:"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Ընտրել` USB կարգաբերումը կասեցնելու համար:"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Վրիպակի զեկույցի ստեղծում…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Տրամադրե՞լ վրիպակի զեկույցը:"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Վրիպակի զեկույցի տրամադրում…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Նորություններ և ամսագրեր"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Քարտեզներ և նավարկում"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Աշխատանք"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Սարքի հիշողություն"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b9771d6..839fc04 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Mengontrol tingkat zoom dan pemosisian layar."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Melakukan isyarat"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Dapat mengetuk, menggesek, mencubit, dan melakukan isyarat lainnya."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestur sidik jari"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Dapat merekam gestur yang dilakukan di sensor sidik jari perangkat."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"nonaktifkan atau ubah bilah status"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"jadikan bilah status"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Ketuk untuk opsi lainnya."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debugging USB terhubung"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Ketuk untuk menonaktifkan debug USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Pilih untuk menonaktifkan debugging USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bagikan laporan bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Membagikan laporan bug..."</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Berita &amp; Majalah"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Peta &amp; Navigasi"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivitas"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Penyimpanan perangkat"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 775c50e..1e2beb0 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Stjórnaðu aðdrætti og afstöðu skjásins."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Nota bendingar"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Getur ýtt, strokið, fært fingur saman og gert ýmsar aðrar bendingar."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingrafarabendingar"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Getur fangað bendingar sem eru gerðar á fingrafaraskynjara tækisins."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"slökkva á eða breyta stöðustiku"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"vera stöðustikan"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Ýttu til að sjá fleiri valkosti."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-villuleit tengd"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Ýttu til að slökkva á USB-villuleit."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Tekur við villutilkynningu…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Deila villutilkynningu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deilir villutilkynningu..."</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Fréttir og tímarit"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kort og leiðsögn"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Aðstoð"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Geymslurými tækis"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index cb4769c..0b7820e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlla il livello di zoom e la posizione del display."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Esegui gesti"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesti con sensore di impronte digitali"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"È in grado di rilevare i gesti compiuti con il sensore di impronte digitali dei dispositivi."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disattivare o modificare la barra di stato"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ruolo di barra di stato"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tocca per altre opzioni."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debug USB collegato"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tocca per disattivare il debug USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleziona per disattivare il debug USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Recupero della segnalazione di bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Condividere la segnalazione di bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Condivisione della segnalazione di bug…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Notizie e riviste"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Maps e Navigatore"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produttività"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Memoria dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index d33cd08..4361ff2 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"קבע את המרחק מהתצוגה ואת מיקום התצוגה."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ביצוע תנועות"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"תנועות"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"אפשרות לזהות תנועות בזמן נגיעה בחיישן טביעות האצבע של המכשיר"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"השבת או שנה את שורת המצב"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"להיות שורת הסטטוס"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"הקש לקבלת אפשרויות נוספות."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏ניפוי באגים של USB מחובר"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"‏הקש כדי להשבית ניפוי באגים של USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"‏בחר להשבית ניפוי באגים ב-USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"עיבוד דוח על באג..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"האם לשתף דוח על באג?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"שיתוף דוח על באג…"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"חדשות וכתבי עת"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"מפות וניווט"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"פרודוקטיביות"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"שטח האחסון במכשיר"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3992e6e..f3a22ce 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"画面のズームレベルと位置を制御します。"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"操作の実行"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"タップ、スワイプ、ピンチ、その他の操作を行えます。"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指紋認証センサーでの操作"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"端末の指紋認証センサーで行われた操作をキャプチャできます。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ステータスバーの無効化や変更"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ステータスバーへの表示"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"タップしてその他のオプションを表示します。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"タップして USB デバッグを無効にします。"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USBデバッグを無効にする場合に選択します。"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"バグレポートを取得しています…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"バグレポートを共有しますか?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"バグレポートの共有中…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ニュース&雑誌"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"地図&ナビ"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"仕事効率化"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"端末のストレージ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1fb7d13..9d3b288 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ეკრანის მასშტაბირების დონისა და პოზიციის მართვა."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ჟესტების შესრულება"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"შეუძლია შეხება, გადაფურცვლა, მასშტაბირება და სხვა ჟესტების შესრულება."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"თითის ანაბეჭდის ჟესტები"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"შეუძლია აღბეჭდოს მოწყობილობის თითის ანაბეჭდის სენსორზე განხორციელებული ჟესტები."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"სტატუსის ზოლის ჩანაცვლება"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"შეეხეთ დამატებითი ვარიანტების სანახავად."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB გამართვა შეერთებულია"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"შეეხეთ USB-გამართვის გასათიშად."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"მონიშნეთ რათა შეწყვიტოთ USB-ის გამართვა"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის შექმნა…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"გსურთ ხარვეზის შესახებ ანგარიშის გაზიარება?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის გაზიარება…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ახალი ამბები და ჟურნალები"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"რუკები და ნავიგაცია"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"პროდუქტიულობა"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"მოწყობილობის მეხსიერება"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 87958c7..b168b6f 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Дисплейдің масштабтау деңгейін және орналастыруды басқару."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Қимылдарды орындау"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Түртуге, сырғытуға, қысуға және басқа қимылдарды орындауға болады."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Саусақ ізі датчигіндегі қимылдар"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Құрылғының саусақ ізі датчигінде орындалған қимылдарды сақтайды"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"күй жолағы болу"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Қосымша опциялар үшін түртіңіз."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB жөндеу қосылған"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB түзетуін өшіру үшін түртіңіз."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп алынуда…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Қате туралы есепті бөлісу керек пе?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Қате туралы есеп бөлісілуде…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Газеттер және журналдар"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карта және навигация"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Өнімділік"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Құрылғы жады"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index f92eff5..0a57834 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"គ្រប់គ្រងការកំណត់ទីតាំង និងកម្រិតពង្រីករបស់អេក្រង់"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ធ្វើកាយវិការ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ចលនា​ស្នាមម្រាមដៃ"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"អាចថត​ចលនា​ដែលមាន​សកម្មភាព​នៅលើ​ឧបករណ៍​ចាប់​ស្នាម​ម្រាមដៃ​របស់ឧបករណ៍។"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"បិទ ឬ​កែ​របារ​ស្ថានភាព"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ឲ្យ​កម្មវិធី​បិទ​របារ​ស្ថានភាព ឬ​បន្ថែម និង​លុប​រូប​តំណាង​ប្រព័ន្ធ។"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ធ្វើជារបារស្ថានភាព"</string>
@@ -1148,6 +1150,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"ប៉ះសម្រាប់ជម្រើសជាច្រើនទៀត"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"បាន​ភ្ជាប់​ការ​កែ​កំហុស​យូអេសប៊ី"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"ប៉ះដើម្បីបិទដំណើរការកែកំហុសយូអេសប៊ី"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"ជ្រើស​ ដើម្បី​បិទ​ការ​កែ​កំហុស​យូអេសប៊ី។"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"កំពុងទទួលយករបាយការណ៍កំហុស…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ចែករំលែករបាយការណ៍កំហុសឬ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"កំពុងចែករំលែករបាយកំហុស…"</string>
@@ -1691,4 +1694,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ព័ត៌មាន និង​ទស្សនាវដ្ដី"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"ផែនទី និង​ការ​រុករក"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ផលិត​ភាព"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ទំហំផ្ទុកឧបករណ៍"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 5c53b1c..07400f5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಾನ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಿ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್‌ಗಳನ್ನು ಮಾಡಬಹುದು."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ ಸೂಚಕಗಳು"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ಸಾಧನದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್‌ನಲ್ಲಿ ನಡೆಸಿದ ಸೂಚಕಗಳನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ಡೀಬಗಿಂಗ್‌‌ ಸಂಪರ್ಕ"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ಡೀಬಗ್‌ ಮಾಡುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ದೋಷದ ವರದಿಯನ್ನು ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತಿದೆ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ಬಗ್ ವರದಿಯನ್ನು ಹಂಚುವುದೇ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲಾಗುತ್ತಿದೆ…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ಸುದ್ದಿ ಮತ್ತು ನಿಯತಕಾಲಿಕೆಗಳು"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"ನಕ್ಷೆಗಳು ಮತ್ತು ನ್ಯಾವಿಗೇಶನ್"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ಉತ್ಪಾದಕತೆ"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ಸಾಧನ ಸಂಗ್ರಹಣೆ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ca70e45..b74094e 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"디스플레이의 확대/축소 수준 및 위치를 제어합니다."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"동작 실행"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"탭, 스와이프, 확대/축소 및 기타 동작을 실행할 수 있습니다."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"지문 동작"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"기기 지문 센서에서 동작을 캡처합니다."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"상태 표시줄 사용 중지 또는 수정"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"상태 표시줄에 위치"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"옵션을 더 보려면 탭하세요."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB 디버깅 연결됨"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB 디버깅을 사용하지 않으려면 탭하세요."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB 디버깅을 사용하지 않으려면 선택합니다."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"버그 보고서 가져오는 중..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"버그 보고서를 공유하시겠습니까?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"버그 신고서 공유 중..."</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"뉴스/잡지"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"지도/내비게이션"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"생산성"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"기기 저장용량"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 94b84f2..7b1d126 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Экрандагы сүрөттүн өлчөмүн өзгөртүү жана жайгаштыруу."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Жаңсоолорду аткаруу"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Таптап, серпип, чымчып жана башка жаңсоолорду аткара алат."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Манжа изинин жаңсоолору"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Түзмөктөрдөгү манжа изинин сенсорунда жасалган жаңсоолорду жаздырып алат."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"абал тилкесин өчүрүү же өзгөртүү"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"абал тилкесинин милдетин аткаруу"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Кошумча параметрлерди ачуу үчүн таптап коюңуз."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB аркылуу мүчүлүштүктөрдү оңдоо туташтырылган"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB арклуу мүчүлштктрдү жоюну өчр үчн тийп коюңуз."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Мүчүлүштүк тууралуу баяндама бөлүшүлсүнбү?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Мүчүлүштүк тууралуу баяндама бөлүшүлүүдө…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Жаңылыктар жана журналдар"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карталар жана чабыттоо"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Өндүрүш категориясы"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Түзмөктүн сактагычы"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 816eea2..5d7b4c3 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ຄວບຄຸມລະດັບການຊູມ ແລະການວາງຕຳແໜ່ງຂອງຈໍສະແດງຜົນ."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ດຳເນີນທ່າທາງຕ່າງໆ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ສາມາດແຕະ, ປັດນີ້ວມື, ຢິບນິ້ວມື ແລະ ດຳເນີນທ່າທາງອື່ນ."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ທ່າທາງລາຍນິ້ວມື"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ສາມາດບັນທຶກທ່າທາງທີ່ເກີດຂຶ້ນໃນອຸປະກອນເຊັນເຊີລາຍນິ້ວມືໄດ້."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ເປັນ​ແຖບ​ສະ​ຖາ​ນະ"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"ແຕະເພື່ອເບິ່ງຕົວເລືອກເພີ່ມເຕີມ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"ເຊື່ອມຕໍ່ການດີບັ໊ກຜ່ານ USB ແລ້ວ"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"ແຕະເພື່ອປິດການດີບັກຜ່ານ USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"ເລືອກເພື່ອປິດການດີບັ໊ກຜ່ານ USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ກຳລັງຂໍລາຍງານຂໍ້ຜິດພາດ…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ແບ່ງປັນລາຍງານບັນຫາບໍ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ກຳລັງແບ່ງປັນລາຍງານບັນຫາ…"</string>
@@ -1202,8 +1205,8 @@
     <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພລິ​ເຄ​ຊັນ​ອ່ານ​ເຊດ​ຊັນ​ການ​ຕິດ​ຕັ້ງ​ໄດ້. ນີ້​ຈະ​ອະ​ນຸ​ຍາດ​ໃຫ້​ມັນ​ເບິ່ງ​ເຫັນ​ລາຍ​ລະ​ອຽດ​ກ່ຽວ​ກັບ​ການ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ​ທີ່​ເຮັດ​​ວຽກ​ຢູ່​ໄດ້."</string>
     <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ຂໍ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ"</string>
     <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ຂອງ​ການ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ."</string>
-    <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"request delete packages"</string>
-    <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ຂອງ​ການ​ຕິດ​ຕັ້ງ​ແພັກ​ເກດ."</string>
+    <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"ຮ້ອງຂໍການລຶບແພັກເກດ"</string>
+    <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຮ້ອງຂໍການລຶບແພັກເກດ."</string>
     <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ຖາມເພື່ອໃຫ້ເພີກເສີຍການປັບແຕ່ງແບັດເຕີຣີ"</string>
     <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ອະນຸຍາດໃຫ້ແອັບຖາມສິດອະນຸຍາດເພື່ອເພີກເສີຍຕໍ່ການປັບແຕ່ງແບັດເຕີຣີສຳລັບແອັບນັ້ນ."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ແຕະສອງເທື່ອເພື່ອຄວບຄຸມການຊູມ"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"News &amp; Magazines"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Maps &amp; Navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ຜະລິດຕະພາບ"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ບ່ອນຈັດເກັບຂໍ້ມູນອຸປະກອນ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 837134c..89ac3f2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Valdykite ekrano mastelio keitimo lygį ir pozicijos nustatymą."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Veiksmai gestais"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Galima paliesti, perbraukti, suimti ir atlikti kitus veiksmus gestais."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Kontrolinio kodo gestai"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Gali užfiksuoti gestus, atliktus naudojant įrenginio kontrolinio kodo jutiklį."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"išjungti ar keisti būsenos juostą"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"būti būsenos juosta"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Palieskite, kad būtų rodoma daugiau parinkčių."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB derinimas prijungtas"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Palieskite, kad išjungtumėte USB derinimą."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Pasirinkite, kas išjungtumėte USB derinimą."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Pateikiamas pranešimas apie riktą…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bendrinti pranešimą apie riktą?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bendrinamas pranešimas apie riktą..."</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Naujienos ir žurnalai"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Žemėlapiai ir navigacija"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktyvumas"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Įrenginio saugykla"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7510e77..5163334 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -281,6 +281,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolējiet displeja tālummaiņas līmeni un pozicionēšanu."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Žestu izpilde"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Atbalsta pieskaršanos, vilkšanu, savilkšanu un citus žestus."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Pirksta nospieduma žesti"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Var uztvert žestus ierīces pirksta nospieduma sensorā."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"atspējot vai pārveidot statusa joslu"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"Būt par statusa joslu"</string>
@@ -1166,6 +1168,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Pieskarieties, lai skatītu citas iespējas."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB atkļūdošana ir pievienota."</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Pieskarieties, lai atspējotu USB atkļūdošanu."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Atlasiet, lai atspējotu USB atkļūdošanu."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Notiek kļūdas pārskata izveide…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vai kopīgot kļūdas pārskatu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Notiek kļūdas pārskata kopīgošana…"</string>
@@ -1720,4 +1723,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Ziņas un žurnāli"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kartes un navigācija"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivitāte"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Ierīces krātuve"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 0e3862f..66d5387 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Контролирајте го нивото на зумирање и позиционирање на екранот."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Користете движења"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Може да допрете, повлечете, штипнете и да користите други движења."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Движења за отпечатоци"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Може да сними движења што се направени на сензорот за отпечатоци на уредите."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"оневозможи или измени статусна лента"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"да стане статусна лента"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Допрете за повеќе опции."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Поврзано е отстранување грешки преку УСБ"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Допрете за да се оневозможи отстранувањето грешки преку USB."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Се зема извештајот за грешки…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Да се сподели извештајот за грешки?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Се споделува извештај за грешки…"</string>
@@ -1691,4 +1695,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Вести и списанија"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карти и навигација"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Продуктивност"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Простор на уредот"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index da97cf5..bb5455d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ഡിസ്പ്ലേയുടെ സൂം നിലയും പൊസിഷനിംഗും നിയന്ത്രിക്കുക."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ജെസ്‌റ്ററുകൾ നിർവഹിക്കുക"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്‌റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ഫിംഗർപ്രിന്റ് ജെസ്‌റ്ററുകൾ"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ഉപകരണത്തിന്റെ ഫിംഗർപ്രിന്റ് സെൻസറിൽ ചെയ്‌ത ജെസ്‌റ്ററുകൾ ക്യാപ്‌ചർ ചെയ്യാനാകും."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്‌ക്കരിക്കുക"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്‌റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ഡീബഗ്ഗിംഗ് കണക്‌റ്റുചെയ്‌തു"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ഡീബഗ്ഗിംഗ് പ്രവർത്തനരഹിതമാക്കാൻ ടാപ്പുചെയ്യുക."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നു…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ബഗ് റിപ്പോർട്ട് പങ്കിടണോ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നു…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"വാർത്തകളും മാസികകളും"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"മാപ്സും നാവിഗേഷനും"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ഉല്‍‌പ്പാദനക്ഷമത"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ഉപകരണ സ്റ്റോറേജ്"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 2af81c4..0f7d43a 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Дэлгэцийн томруулах түвшин болон байршлыг хянах."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Зангах"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Товших, шудрах, жижигрүүлэх болон бусад зангааг хийх боломжтой."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Хурууны хээний зангаа"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Төхөөрөмжийн хурууны хээ мэдрэгчид зангасан зангааг танина."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"статусын хэсэг болох"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Бусад сонголтыг харахын тулд товшино уу."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB дебаг холбогдсон"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB-н алдаа засварлахыг идэвхгүй болгохын тулд товшино уу."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB дебаг хийхийг идэвхгүй болгох бол сонгоно уу."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Алдааны тайланг авч байна..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Алдааны тайланг хуваалцах уу?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Алдааны тайланг хуваалцаж байна..."</string>
@@ -1687,4 +1690,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Мэдээ &amp; сэтгүүл"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Газрын зураг &amp; зүг чиг"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Бүтээмж"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Төхөөрөмжийн сан"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 1be89c2..69cf831 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनाचा झूम स्तर आणि स्थिती निर्धारण नियंत्रित करा."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"जेश्चर करा"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"टॅप, स्वाइप, पिंच आणि इतर जेश्चर करू शकते."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिंट जेश्चर"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"डिव्‍हाइसच्‍या फिंगरप्रिंट सेंसरवर केलेले जेश्चर कॅप्‍चर करू शकते."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टीम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"स्टेटस बार होऊ द्या"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"अधिक पर्यायांसाठी टॅप करा."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग करणे कनेक्‍ट केले"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB डीबग करणे अक्षम करण्यासाठी टॅप करा."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"दोष अहवाल घेत आहे..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल सामायिक करायचा?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"दोष अहवाल सामायिक करीत आहे..."</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"बातम्‍या आणि मासिके"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"नकाशे आणि नेव्हिगेशन"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"उत्पादनक्षमता"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"डिव्‍हाइस संचय"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index ad1f4cb..ad053b9 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kawal tahap zum dan kedudukan paparan."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Lakukan gerak isyarat"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Boleh ketik, leret, cubit dan laksanakan gerak isyarat lain."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gerak isyarat cap jari"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Boleh menangkap gerak isyarat yang dilakukan pada penderia cap jari peranti."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"lumpuhkan atau ubah suai bar status"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"jadi bar status"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Ketik untuk mendapatkan lagi pilihan."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Penyahpepijatan USB disambungkan"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Ketik untuk melumpuhkan penyahpepijatan USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Pilih untuk melumpuhkan penyahpepijatan USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Mengambil laporan pepijat…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Kongsi laporan pepijat?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Berkongsi laporan pepijat…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Berita &amp; Majalah"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Peta &amp; Navigasi"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktiviti"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Storan peranti"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 129eefd..4454c2b5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် ဇူးမ်အရွယ်နှင့် နေရာချထားခြင်းကို ထိန်းချုပ်ပါ။"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"လက်ဟန်များ အသုံးပြုပါ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"လက်ဗွေရာများ"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ကိရိယာ၏ လက်ဗွေအာရုံခံကိရိယာတွင် နှိပ်ထားသည်များကို မှတ်သားထားနိုင်သည်။"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"အက်ပ်အား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"နောက်ထပ်ရွေးချယ်စရာများအတွက် တို့ပါ။"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB အမှားစစ်ခြင်းအား ချိတ်ဆက်ထားသည်"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ဆက်သွယ်ရေးစနစ်ကို ပိတ်ရန် တို့ပါ။"</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ချွတ်ယွင်းချက် အစီရင်ခံစာပြုစုနေသည်..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ချွတ်ယွင်းချက် အစီရင်ခံစာကို မျှဝေမလား။"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ချွတ်ယွင်းမှုအစီရင်ခံစာ မျှဝေနေသည်…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"သတင်းနှင့် မဂ္ဂဇင်းများ"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"မြေပုံနှင့် ခရီးလမ်းညွှန်ချက်"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ထုတ်လုပ်နိုင်မှု"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"စက်ပစ္စည်း သိုလှောင်ခန်း"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9ef1bb3..d23441f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér zoomenivået og plasseringen for skjermen."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gjøre bevegelser"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, sveipe, klype og gjøre andre bevegelser."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Bevegelser på fingeravtrykkssensor"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan fange inn bevegelser som utføres på enhetens fingeravtrykkssensor."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"deaktivere eller endre statusfeltet"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"vise appen i statusfeltet"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Trykk for å få flere alternativ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-feilsøking tilkoblet"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Trykk for å slå av feilsøking via USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Velg for å deaktivere USB-debugging."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kjører feilrapport …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vil du dele feilrapporten?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deler feilrapporten …"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Nyheter og tidsskrifter"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kart og navigering"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Lagring på enheten"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 6ebbc93..d513ff3 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनको जुम स्तर र स्थिति नियन्त्रण गर्नुहोस्।"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"इसाराहरू सम्बन्धी कार्य गर्नुहोस्"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सक्छ"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिन्टका इसाराहरू"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"यन्त्रहरूक‍ो फिंगरप्रिन्ट सेन्सरमा गरिएका इसाराहरू कैद गर्न सक्छ।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string>
@@ -1152,6 +1154,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"थप विकल्पहरूका लागि ट्याप गर्नुहोस्।"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डिबग गर्ने जडित छ"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB डिबगिङलाई असक्षम गर्न ट्याप गर्नुहोस्।"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डिबगिङ असक्षम पार्न चयन गर्नुहोस्।"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रिपोर्ट लिँदै..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग रिपोर्टलाई साझेदारी गर्ने हो?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रिपोर्टलाई साझेदारी गर्दै ..."</string>
@@ -1695,4 +1698,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"समाचार तथा पत्रिकाहरू"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"नक्सा तथा नेभिगेसन"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"उत्पादकत्व"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"यन्त्रको भण्डारण"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8ece49e..f3e0274 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Bedien het zoomniveau en de positionering van het scherm."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gebaren uitvoeren"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan tikken, vegen, samenknijpen en andere gebaren uitvoeren."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Vingerafdrukgebaren"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"statusbalk uitschakelen of wijzigen"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Hiermee kan de app de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"de statusbalk zijn"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tik voor meer opties."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-foutopsporing verbonden"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tik om USB-foutopsporing uit te schakelen."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecteer deze optie om USB-foutopsporing uit te schakelen."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Bugrapport genereren…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Bugrapport delen?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Bugrapport delen…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Nieuws en tijdschriften"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Maps en navigatie"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productiviteit"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Apparaatopslag"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 8438fb9..788efb8 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ਡਿਸਪਲੇ ਦੇ ਜ਼ੂਮ ਪੱਧਰ ਅਤੇ ਸਥਿਤੀ ਨੂੰ ਨਿਯੰਤ੍ਰਿਤ ਕਰੋ।"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ਸੰਕੇਤ ਕਰਦੀ ਹੈ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਪਿੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਕੇਤ"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ਸਥਿਤੀ ਬਾਰ ਅਸਮਰੱਥ ਬਣਾਓ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਜਾਂ ਸਿਸਟਮ ਆਈਕਨਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ਡੀਬਗਿੰਗ ਕਨੈਕਟ ਕੀਤੀ"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ਡੀਬੱਗਿੰਗ ਨੂੰ ਅਯੋਗ ਬਣਾਉਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ਬੱਗ ਰਿਪਰੋਟ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ਕੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ਖਬਰਾਂ ਅਤੇ ਰਸਾਲੇ"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"ਨਕਸ਼ੇ ਅਤੇ ਆਵਾਗੌਣ"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ਉਤਪਾਦਕਤਾ"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"ਡੀਵਾਈਸ ਸਟੋਰੇਜ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 125f3f2..3814f80 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Regulowanie poziomu i obszaru powiększenia ekranu."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Obsługa gestów"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Obsługuje kliknięcia, przesunięcia, ściągnięcia palców i inne gesty."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesty związane z odciskiem palca"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Może przechwytywać gesty wykonywane na czytniku linii papilarnych w urządzeniu."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"wyłączanie lub zmienianie paska stanu"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"działanie jako pasek stanu"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Kliknij, by wyświetlić więcej opcji."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Podłączono moduł debugowania USB"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Kliknij, by wyłączyć debugowanie USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Wybierz, aby wyłączyć debugowanie USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zgłaszam błąd…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Udostępnić raport o błędzie?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Udostępniam raport o błędzie…"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Wiadomości i czasopisma"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapy i nawigacja"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktywność"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Pamięć urządzenia"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c6d217a..a7a763f 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o posicionamento e nível de zoom da tela."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Toque para ver mais opções."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração do USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Notícias e revistas"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegação"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Armazenamento do dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index eabc2f4..b87fe9e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o nível de zoom e o posicionamento do ecrã."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"É possível tocar, deslizar rapidamente, juntar os dedos e realizar outros gestos"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode capturar gestos realizados no sensor de impressões digitais do dispositivo."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar barra de estado"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite à aplicação desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ser apresentada na barra de estado"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Toque para obter mais opções."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB ligada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Seleccione para desativar depuração USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"A criar relatório de erro…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Pretende partilhar o relatório de erro?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"A partilhar relatório de erro…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Notícias e revistas"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegação"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Armazenamento do dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c6d217a..a7a763f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o posicionamento e nível de zoom da tela."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestos de impressão digital"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Pode captar gestos realizados no sensor de impressão digital do dispositivo."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Toque para ver mais opções."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuração USB conectada"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Toque para desativar a depuração do USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selecione para desativar a depuração USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Gerando relatório do bug..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Compartilhar relatório do bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Compartilhando relatório do bug…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Notícias e revistas"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapas e navegação"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produtividade"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Armazenamento do dispositivo"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5e7df4b..b407ae0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -281,6 +281,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlați nivelul de zoom și poziționarea afișajului."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Folosiți gesturi"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Se poate atinge, glisa, ciupi și se pot folosi alte gesturi."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesturi ce implică amprente"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Poate reda gesturile făcute pe senzorul de amprentă al dispozitivelor."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"dezactivare sau modificare bare de stare"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"să fie bara de stare"</string>
@@ -1166,6 +1168,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Atingeți pentru mai multe opțiuni."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depanarea USB este conectată"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Atingeți ca să dezactivați remedierea erorilor prin USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Selectați pentru a dezactiva depanarea USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Se creează un raport de eroare…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Trimiteți raportul de eroare?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Se trimite raportul de eroare…"</string>
@@ -1720,4 +1723,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Știri și reviste"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Hărți și navigare"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivitate"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Stocare pe dispozitiv"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 5aabe4d..2e2bd0b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управлять позиционированием и размером изображения на экране."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Жесты"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Может выполнять жесты нажатия, пролистывания, масштабирования и т. д."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жесты для отпечатков пальцев"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Сохраняет жесты, выполненные на сканере отпечатков пальцев."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Отключение/изменение строки состояния"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"Замена строки состояния"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Нажмите, чтобы показать дополнительные параметры."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отладка по USB разрешена"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Нажмите, чтобы отключить отладку по USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Нажмите, чтобы отключить отладку USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Подготовка отчета об ошибке"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Разрешить доступ к информации об ошибке?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Отправка отчета об ошибке"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Новости и журналы"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карты и навигация"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Работа"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Хранилище устройства"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index d776aaa..7440888 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"සංදර්ශනයේ විශාලන මට්ටම සහ පිහිටීම පාලනය කරන්න."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"අභින සිදු කරන්න"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"තට්ටු කිරීමට, ස්වයිප් කිරීමට, පින්ච් කිරීමට, සහ වෙනත් අභින සිදු කිරීමට හැකිය."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ඇඟිලි සලකුණු ඉංගිත"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"උපාංග ඇඟිලි සලකුණු සංවේදකය මත සිදු කරන ඉංගිත ග්‍රහණය කළ හැකිය."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"තත්ව තීරුව අක්‍රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"තත්ත්ව තීරුව බවට පත්වීම"</string>
@@ -1148,6 +1150,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"තවත් විකල්ප සඳහා තට්ටු කරන්න."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB නිදොස්කරණය සම්බන්ධිතයි"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB නිදොස්කරණය අබල කිරීමට තට්ටු කරන්න."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB නිදොස්කරණය අබල කිරීමට තෝරන්න."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"දෝෂ වාර්තාවක් ගනිමින්…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"දෝෂ වාර්තාව බෙදා ගන්නද?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"දෝෂ වාර්තාවක් බෙදා ගනිමින්..."</string>
@@ -1691,4 +1694,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"පුවත් සහ සඟරා"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"සිතියම් සහ සංචලනය"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ඵලදායිතාව"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"උපාංග ගබඩාව"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c7b094a..47716da 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ovládajte úroveň priblíženia/oddialenia obrazovky a umiestnenie"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gestá"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gestá odtlačkov prstov"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Dokáže zaznamenať gestá vykonané na senzore odtlačkov prstov."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázanie alebo zmeny stavového riadka"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"vydávanie sa za stavový riadok"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Klepnutím zobrazíte ďalšie možnosti."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladenie cez USB pripojené"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Klepnutím zakážete ladenie cez USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Výberom zakážete ladenie USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Preberá sa hlásenie chyby…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chcete zdieľať hlásenie chyby?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Zdieľa sa hlásenie chyby…"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Noviny a časopisy"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mapy a navigácia"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivita"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Úložisko zariadenia"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ab8264c..13102b5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Nadziranje stopnje povečave in položaja prikaza."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Izvajanje potez"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Mogoče je izvajanje dotikov, vlečenja, primikanja in razmikanja prstov ter drugih potez."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Poteze po tipalu prstnih odtisov"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Prepoznava poteze, narejene po tipalu prstnih odtisov naprave."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"onemogočanje ali spreminjanje vrstice stanja"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"postane vrstica stanja"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Dotaknite se za več možnosti."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Iskanje napak prek USB je povezano"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Dotaknite se za izklop odpravljanja napak prek USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Izberite, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Zajemanje poročila o napakah …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite poslati poročilo o napakah?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Pošiljanje poročila o napakah …"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Novice in revije"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Zemljevidi in navigacija"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Storilnost"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Shramba naprave"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index fc9384c..fd76f7d 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollo nivelin dhe pozicionimin e zmadhimit të ekranit."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Kryen gjeste"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Mund të trokasë, rrëshqasë, bashkojë gishtat dhe kryejë gjeste të tjera."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gjestet e gjurmës së gishtit"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Mund të kapë gjestet e kryera në sensorin e gjurmës së gishtit të pajisjeve."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"çaktivizo ose modifiko shiritin e statusit"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"të bëhet shiriti i statusit"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Trokit për më shumë opsione."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Korrigjuesi i USB-së i lidhur"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Trokit për të çaktivizuar korrigjimin e gabimeve të USB-së."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Po merret raporti i defekteve në kod…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Të ndahet raporti i defektit në kod?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Po ndan raportin e defekteve në kod..."</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Lajme dhe revista"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Harta dhe navigim"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Hapësira ruajtëse e pajisjes"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 93253c2..54b0fae 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -281,6 +281,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управља нивоом зумирања приказа и одређивањем положаја."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Обављање покрета"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Може да додирује, листа, скупља приказ и обавља друге покрете."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Покрети за отисак прста"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Може да региструје покрете на сензору за отисак прста на уређају."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"онемогућавање или измена статусне траке"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"функционисање као статусна трака"</string>
@@ -1166,6 +1168,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Додирните за још опција."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је успостављено"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Изаберите да бисте онемогућили отклањања грешака са USB-а."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Извештај о грешци се генерише…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Желите ли да поделите извештај о грешци?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Дели се извештај о грешци…"</string>
@@ -1720,4 +1723,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Новости и часописи"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Мапе и навигација"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Продуктивност"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Меморијски простор уређаја"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 88089b9..e010b96 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Styr skärmens zoomnivå och positionering."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Göra rörelser"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trycka, svepa, nypa och göra andra rörelser."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeravtrycksrörelser"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Kan registrera rörelser som utförs med hjälp av enhetens fingeravtryckssensor."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"inaktivera eller ändra statusfält"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"visas i statusfältet"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Tryck för fler alternativ."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-felsökning ansluten"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Tryck om du vill inaktivera USB-felsökning."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Välj att inaktivera USB-felsökning."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Felrapporten överförs …"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Vill du dela felrapporten?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Felrapporten delas …"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Nyheter och tidskrifter"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Kartor och navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktivitet"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Enhetens lagringsutrymme"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index db6f8cf..c363a2216 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -276,6 +276,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Dhibiti kiwango cha kukuza na nafasi cha onyesho."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Tekeleza ishara"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Unaweza kugonga, kutelezesha kidole, kubana na kutekeleza ishara zingine."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Ishara za alama ya kidole"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Inaweza kurekodi ishara zinazotekelezwa kwenye kitambua alama ya kidole."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zima au rekebisha mwambaa hali"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa ikoni za mfumo."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"kuwa sehemu ya arifa"</string>
@@ -1144,6 +1146,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Gonga ili upate chaguo zaidi."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji wa USB umeunganishwa"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Gonga ili uzime utatuaji wa USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Chagua ili kulemaza utatuaji USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Inatayarisha ripoti ya hitilafu…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Ungependa kushiriki ripoti ya hitilafu?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Inashiriki ripoti ya hitilafu…"</string>
@@ -1687,4 +1690,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Habari na Magazeti"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Ramani na Maelekezo"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Uzalishaji"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Hifadhi ya kifaa"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index e259a39..8a70c4e 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"திரையின் ஜூம் அளவையும் நிலையையும் கட்டுப்படுத்தலாம்."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"சைகைகளைச் செயல்படுத்துதல்"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"தட்டலாம், ஸ்வைப் செய்யலாம், பின்ச் செய்யலாம் மற்றும் பிற சைகைகளைச் செயல்படுத்தலாம்."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"கைரேகை சைகைகள்"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"சாதனத்தின் கைரேகை உணர்வி மேல் செய்யப்படும் சைகைகளைப் படமெடுக்க முடியும்."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"நிலைப் பட்டியில் இருக்கும்"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"மேலும் விருப்பங்களுக்கு, தட்டவும்."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB பிழைதிருத்தம் இணைக்கப்பட்டது"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB பிழை திருத்தத்தை முடக்க, தட்டவும்."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"பிழை அறிக்கையை எடுக்கிறது…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"பிழை அறிக்கையைப் பகிரவா?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"பிழை அறிக்கையைப் பகிர்கிறது…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"செய்திகளும் பத்திரிகைகளும்"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"வரைபடங்களும் வழிசெலுத்தலும்"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"உற்பத்தித்திறன்"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"சாதனச் சேமிப்பகம்"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index dc5653c..4d22092 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"డిస్‌ప్లే జూమ్ స్థాయి మరియు స్థానాన్ని నియంత్రిస్తుంది."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"సంజ్ఞలను చేయడం"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"నొక్కగలరు, స్వైప్ చేయగలరు, స్క్రీన్‌పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగగలరు మరియు ఇతర సంజ్ఞలను చేయగలరు."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"వేలిముద్ర సంజ్ఞలు"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"పరికరాల వేలిముద్ర సెన్సార్‌లో నిర్వహించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"స్థితి బార్‌ను నిలిపివేయడం లేదా సవరించడం"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"స్థితి బార్‌ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"స్థితి పట్టీగా ఉండటం"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"మరిన్ని ఎంపికల కోసం నొక్కండి."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB డీబగ్గింగ్ కనెక్ట్ చేయబడింది"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB డీబగ్గింగ్‌ను నిలిపివేయడానికి నొక్కండి."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"బగ్ నివేదికను తీస్తోంది…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"బగ్ నివేదికను భాగస్వామ్యం చేయాలా?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"బగ్ నివేదికను భాగస్వామ్యం చేస్తోంది..."</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"వార్తలు &amp; వార్తాపత్రికలు"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"మ్యాప్స్ &amp; నావిగేషన్"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ఉత్పాదకత"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"పరికర నిల్వ"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ae84073..38dfd84 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ควบคุมระดับการซูมและการวางตำแหน่งของการแสดงผล"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ทำท่าทางสัมผัส"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"สามารถแตะ เลื่อน บีบ และทำท่าทางสัมผัสอื่นๆ"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ท่าทางสัมผัสลายนิ้วมือ"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"สามารถจับท่าทางสัมผัสที่เกิดขึ้นบนเซ็นเซอร์ลายนิ้วมือของอุปกรณ์"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"เป็นแถบสถานะ"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"แตะเพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"แตะเพื่อปิดใช้การแก้ไขข้อบกพร่องของ USB"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"เลือกเพื่อปิดใช้งานการแก้ไขข้อบกพร่อง USB"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"กำลังสร้างรายงานข้อบกพร่อง…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"แชร์รายงานข้อบกพร่องไหม"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"กำลังแชร์รายงานข้อบกพร่อง…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"ข่าวสารและนิตยสาร"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"แผนที่และการนำทาง"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"ประสิทธิภาพการทำงาน"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"พื้นที่เก็บข้อมูลของอุปกรณ์"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 3ca68da..06c6aa7 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolin ang antas ng pag-zoom at pagpoposisyon ng display."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Magsagawa ng mga galaw"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"May kakayahang mag-tap, mag-swipe, mag-pinch at magsagawa ng iba pang mga galaw."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Mga galaw gamit ang fingerprint"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Makukunan ang mga galaw na ginawa sa sensor para sa fingerprint ng mga device."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"i-disable o baguhin ang status bar"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Pinapayagan ang app na i-disable ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"maging status bar"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"I-tap para sa higit pang mga opsyon."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Konektado ang debugging ng USB"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"I-tap upang i-disable ang pag-debug ng USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Piliin upang i-disable ang debugging ng USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Kinukuha ang ulat ng bug…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Gusto mo bang ibahagi ang ulat ng bug?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Ibinabahagi ang ulat ng bug…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Balita at Mga Magazine"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Mga Mapa at Navigation"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Productivity"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Storage ng device"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 70183a1..c6dd402 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekranın yakınlaştırma seviyesini ve konumunu kontrol edin."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Haraketleri yapma"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Hafifçe dokunabilir, hızlıca kaydırabilir, sıkıştırabilir ve diğer hareketleri yapabilirsiniz."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Parmak izi hareketleri"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Cihazların parmak izi sensörlerinde gerçekleştirilen hareketleri yakalayabilir."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"durum çubuğunu devre dışı bırak veya değiştir"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"durum çubuğunda olma"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Diğer seçenekler için dokunun."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hata ayıklaması bağlandı"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB hata ayıklamasını devre dışı bırakmak için tıklayın."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Hata raporu alınıyor…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Hata raporu paylaşılsın mı?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Hata raporu paylaşılıyor..."</string>
@@ -1232,7 +1235,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirim dinleyici"</string>
-    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Sanal Gerçeklik dinleyici"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR dinleyici"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Durum sağlayıcı"</string>
     <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirim sıralama hizmeti"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Haberler ve Dergiler"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Haritalar ve Navigasyon"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Verimlilik"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Cihazdaki depolama alanı"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3fd1f23..6b5070a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -284,6 +284,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Контролювати масштаб і розташування екрана."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Виконання жестів"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна торкатися, проводити пальцем, стискати пальці та виконувати інші жести."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Жести на сканері відбитків пальців"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Фіксуються жести на сканері відбитків пальців."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"вимикати чи змін. рядок стану"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"відображатися як рядок стану"</string>
@@ -1186,6 +1188,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Торкніться, щоб переглянути більше опцій."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Налагодження USB завершено"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Торкніться, щоб вимкнути налагодження USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Вибер., щоб вимкн. налагодж. USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Створюється повідомлення про помилку…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Надіслати звіт про помилку?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Надсилається звіт про помилку…"</string>
@@ -1751,4 +1754,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Новини та журнали"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Карти й навігація"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Продуктивність"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Пам’ять пристрою"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 86515b3..9f77dbb 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ڈسپلے کے زوم کی سطح اور پوزیشن کو کنٹرول کریں۔"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"اشارے انجام دیں"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"تھپتھپانا، سوائپ کرنا، چٹکی بھرنا اور دیگر اشارے انجام دے سکتی ہے"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"فنگرپرنٹ کے اشارے"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"آلات کے فنگر پرنٹ سینسر پر کیے گئے اشاروں کو کیپچر کر سکتا ہے۔"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"بطور اسٹیٹس بار کام لیں"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"مزید اختیارات کیلئے تھپتھپائیں۔"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"‏USB ڈیبگ کرنا مربوط ہو گیا"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"‏USB ڈیبگنگ کو غیر فعال کرنے کیلئے تھپتھپائیں۔"</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"بگ رپورٹ لی جا رہی ہے…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"بگ رپورٹ کا اشتراک کریں؟"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"بگ رپورٹ کا اشتراک ہو رہا ہے…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"خبریں اور میگزین"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"نقشے اور نیویگیشن"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"پروڈکٹیوٹی"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"آلہ کی اسٹوریج"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 5f978c6..6f07869 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekranni kattalashtirish darajasi va joylashuvini boshqaradi."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Imo-ishoralar bilan boshqarish"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Bosish, surish; jipslashtirish va boshqa imo-ishoralarni amalga oshirish mumkin."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Barmoq izi ishoralari"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Barmoq izi skanerlarida kiritilgan ishoralarni taniy oladi."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"holat panelini o‘zgartirish yoki o‘chirish"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"holat qatorida ko‘rinishi"</string>
@@ -1146,6 +1148,8 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Boshqa parametrlarini ko‘rish uchun bosing."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB orqali nosozliklarni tuzatish"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"O‘chirib qo‘yish uchun bu yerga bosing."</string>
+    <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
+    <skip />
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Xatoliklar hisoboti olinmoqda…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Xatoliklar hisoboti yuborilsinmi?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Xatoliklar hisoboti yuborilmoqda…"</string>
@@ -1689,4 +1693,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Yangiliklar va jurnallar"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Xaritalar va navigatsiya"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Ish va unumdorlik"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Qurilma xotirasi"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index e2c6e32..f2d9c8f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kiểm soát vị trí và mức thu phóng của màn hình."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Thực hiện cử chỉ"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Có thể nhấn, vuốt, chụm và thực hiện các cử chỉ khác."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Cử chỉ vân tay"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Có thể ghi lại các cử chỉ được thực hiện trên cảm biến vân tay của thiết bị."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"trở thành thanh trạng thái"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Nhấn để biết thêm tùy chọn."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Nhấn để vô hiệu hóa gỡ lỗi USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Chọn để vô hiệu hóa gỡ lỗi USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Đang thu thập báo cáo lỗi…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Chia sẻ báo cáo lỗi?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Đang chia sẻ báo cáo lỗi…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Tin tức và tạp chí"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Bản đồ và dẫn đường"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Sản xuất"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Bộ nhớ của thiết bị"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 12f419b..96eba47 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控制显示内容的缩放级别和位置。"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"执行手势"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可执行点按、滑动、双指张合等手势。"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指纹手势"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"可以捕获在设备指纹传感器上执行的手势。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改状态栏"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"允许应用停用状态栏或者增删系统图标。"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"用作状态栏"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"点按即可查看更多选项。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已连接到USB调试"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"点按即可停用 USB 调试功能。"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"选择停用USB调试。"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在生成错误报告…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享错误报告吗?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享错误报告…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"新闻和杂志"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"地图和导航"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"办公"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"设备存储空间"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 9996617..234d45b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控制顯示屏的縮放程度和位置。"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"執行手勢"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可以輕按、快速滑動和兩指縮放,並執行其他手勢。"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指紋手勢"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"可擷取裝置指紋感應器上執行的手勢。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改狀態列"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"成為狀態列"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"輕按即可查看更多選項。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"輕按即可停用 USB 偵錯功能。"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取即可停用 USB 偵錯。"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在取得錯誤報告…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"新聞和雜誌"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"地圖和導航"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"生產力應用程式"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"裝置儲存空間"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 04c5a8e..0f0f176 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控管顯示畫面的縮放等級和位置。"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"使用手勢"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可使用輕觸、滑動和雙指撥動等手勢。"</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"指紋手勢"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"可以擷取在裝置指紋感應器上執行的手勢。"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"停用或變更狀態列"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"以狀態列顯示"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"輕觸即可查看更多選項。"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"輕觸即可停用 USB 偵錯。"</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取以停用 USB 偵錯。"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在接收錯誤報告…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"正在分享錯誤報告…"</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"新聞和雜誌"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"地圖和導航"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"生產應用"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"裝置儲存空間"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 095341a..938b332 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -278,6 +278,8 @@
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Lawula ileveli yokusondeza yesibonisi nendawo."</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Yenza ukuthinta"</string>
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Ingathepha, iswayiphe, incinze, futhi yenze okunye ukuthintwa."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Ukuthinta kwezigxivizo zeminwe"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"Ingathatha ukuthinta okwenziwe kunzwa yezigxivizo zeminwe zamadivayisi."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"khubaza noma guqula ibha yomumo"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"yiba yibha yesimo"</string>
@@ -1146,6 +1148,7 @@
     <string name="usb_notification_message" msgid="3370903770828407960">"Thepha ngezinketho eziningi."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ukulungisa iphutha le-USB kuxhunyiwe"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"Thepha ukuze ukhubaze ukususa isiphazamisi se-USB."</string>
+    <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"Khetha ukuvimbela ukulungisa iphutha le-USB."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Ithatha umbiko wesiphazamisi..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Yabelana ngombiko wesiphazamisi?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Yabelana ngombiko wesiphazamisi..."</string>
@@ -1689,4 +1692,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"Izindaba nomagazini"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"Amamephu nokuzula"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"Ukukhiqiza"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Isitoreji sedivayisi"</string>
+    <!-- no translation found for adb_debugging_notification_channel_tv (5537766997350092316) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c548219..7f49f05 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3392,6 +3392,8 @@
             <flag name="flagRetrieveInteractiveWindows" value="0x00000040" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_ENABLE_ACCESSIBILITY_VOLUME} -->
             <flag name="flagEnableAccessibilityVolume" value="0x00000080" />
+            <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_ACCESSIBILITY_BUTTON} -->
+            <flag name="flagRequestAccessibilityButton" value="0x00000100" />
             <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES} -->
             <flag name="flagCaptureFingerprintGestures" value="0x00000200" />
         </attr>
@@ -3429,18 +3431,9 @@
         <attr name="canRequestFilterKeyEvents" format="boolean" />
         <!-- Attribute whether the accessibility service wants to be able to control
              display magnification.
-             <p>
-             Required to allow setting the {@link android.accessibilityservice
-             #AccessibilityServiceInfo#FLAG_CAN_CONTROL_MAGNIFICATION} flag.
-             </p>
          -->
         <attr name="canControlMagnification" format="boolean" />
-        <!-- Attribute whether the accessibility service wants to be able to perform gestures.
-             <p>
-             Required to allow setting the {@link android.accessibilityservice
-             #AccessibilityServiceInfo#FLAG_CAN_PERFORM_GESTURES} flag.
-             </p>
-         -->
+        <!-- Attribute whether the accessibility service wants to be able to perform gestures. -->
         <attr name="canPerformGestures" format="boolean" />
         <!-- Attribute whether the accessibility service wants to be able to capture gestures from
              the fingerprint sensor.
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 927988f..9824051 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -475,9 +475,6 @@
 
     <dimen name="chooser_grid_padding">0dp</dimen>
 
-    <item type="dimen" format="integer" name="time_picker_column_start_material">0</item>
-    <item type="dimen" format="integer" name="time_picker_column_end_material">1</item>
-
     <item type="dimen" name="aerr_padding_list_top">15dp</item>
     <item type="dimen" name="aerr_padding_list_bottom">8dp</item>
 
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index ebe577c..e3fdcec 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -149,6 +149,7 @@
     <dimen name="timepicker_radial_picker_dimen">296dp</dimen>
     <dimen name="timepicker_radial_picker_top_margin">16dp</dimen>
     <dimen name="timepicker_radial_picker_horizontal_margin">16dp</dimen>
+    <dimen name="timepicker_edit_text_size">24sp</dimen>
 
     <!-- Used by RadialTimePicker in clock-style TimePicker. -->
     <dimen name="timepicker_selector_radius">20dp</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e00874f..19c5643 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4471,4 +4471,20 @@
     <string name="device_storage_monitor_notification_channel">Device storage</string>
     <!-- Channel name for UsbDeviceManager adb debugging notifications -->
     <string name="adb_debugging_notification_channel_tv">USB debugging</string>
+
+    <!-- Label for the time picker hour input field. [CHAR LIMIT=20] -->
+    <string name="time_picker_hour_label">hour</string>
+    <!-- Label for the time picker minute input field. [CHAR LIMIT=20] -->
+    <string name="time_picker_minute_label">minute</string>
+    <!-- The title for the time picker dialog. [CHAR LIMIT=NONE] -->
+    <string name="time_picker_header_text">Set time</string>
+    <!-- Error shown to the user if they type in invalid hour or minute in the time picker. [CHAR LIMIT=NONE] -->
+    <string name="time_picker_input_error">Enter a valid time</string>
+    <!-- Label shown to the user in time picker to let them know that should type in time. [CHAR LIMIT=NONE] -->
+    <string name="time_picker_prompt_label">Type in time</string>
+    <!-- Accessibility string used for describing the button in time picker that changes the dialog to text input mode. [CHAR LIMIT=NONE] -->
+    <string name="time_picker_text_input_mode_description">Switch to text input mode for the time input.</string>
+    <!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
+    <string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
+
 </resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 1e15348..8f061a3 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -426,6 +426,21 @@
         <item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
     </style>
 
+    <style name="TextAppearance.Material.TimePicker.InputHeader" parent="TextAppearance.Material">
+        <item name="textSize">@dimen/text_size_display_1_material</item>
+        <item name="textColor">@color/white</item>
+        <item name="fontFamily">sans-serif-medium</item>
+    </style>
+
+    <style name="TextAppearance.Material.TimePicker.InputField" parent="TextAppearance.Material">
+        <item name="textSize">@dimen/timepicker_edit_text_size</item>
+    </style>
+
+    <style name="TextAppearance.Material.TimePicker.PromptLabel" parent="TextAppearance.Material">
+        <item name="textSize">@dimen/timepicker_text_size_normal</item>
+        <item name="fontFamily">sans-serif-medium</item>
+    </style>
+
     <style name="TextAppearance.Material.DatePicker.YearLabel" parent="TextAppearance.Material">
         <item name="textColor">@color/primary_text_secondary_when_activated_material_inverse</item>
         <item name="textSize">@dimen/date_picker_year_label_size</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b95c20b..8f3ba87 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -120,6 +120,7 @@
   <java-symbol type="id" name="permission_list" />
   <java-symbol type="id" name="pickers" />
   <java-symbol type="id" name="prefs" />
+  <java-symbol type="id" name="prefs_container" />
   <java-symbol type="id" name="prefs_frame" />
   <java-symbol type="id" name="prev" />
   <java-symbol type="id" name="progress" />
@@ -2842,4 +2843,24 @@
   <!-- Accessibility fingerprint gestures -->
   <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
   <java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" />
+
+  <!-- Time picker -->
+  <java-symbol type="id" name="toggle_mode"/>
+  <java-symbol type="id" name="input_mode"/>
+  <java-symbol type="id" name="input_header"/>
+  <java-symbol type="id" name="input_separator"/>
+  <java-symbol type="id" name="input_hour"/>
+  <java-symbol type="id" name="input_minute"/>
+  <java-symbol type="id" name="am_pm_spinner"/>
+  <java-symbol type="id" name="label_hour"/>
+  <java-symbol type="id" name="label_minute"/>
+  <java-symbol type="id" name="label_error"/>
+  <java-symbol type="layout" name="time_picker_text_input_material"/>
+  <java-symbol type="drawable" name="btn_keyboard_key_material"/>
+  <java-symbol type="drawable" name="btn_event_material"/>
+  <java-symbol type="string" name="time_picker_text_input_mode_description"/>
+  <java-symbol type="string" name="time_picker_radial_mode_description"/>
+
+  <!-- resolver activity -->
+  <java-symbol type="drawable" name="resolver_icon_placeholder" />
 </resources>
diff --git a/core/tests/coretests/src/android/net/RecommendationRequestTest.java b/core/tests/coretests/src/android/net/RecommendationRequestTest.java
index bd25500..e2e6883 100644
--- a/core/tests/coretests/src/android/net/RecommendationRequestTest.java
+++ b/core/tests/coretests/src/android/net/RecommendationRequestTest.java
@@ -96,7 +96,7 @@
 
         RecommendationRequest parceled = passThroughParcel(request);
 
-        assertEquals(0, parceled.getLastSelectedNetworkId());
+        assertEquals(-1, parceled.getLastSelectedNetworkId());
         assertEquals(0, parceled.getLastSelectedNetworkTimestamp());
     }
 
diff --git a/core/tests/coretests/src/android/provider/SettingsTest.java b/core/tests/coretests/src/android/provider/SettingsTest.java
index d76980a..1ff2056 100644
--- a/core/tests/coretests/src/android/provider/SettingsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsTest.java
@@ -392,7 +392,6 @@
                  Settings.Secure.BACKUP_PROVISIONED,
                  Settings.Secure.BACKUP_TRANSPORT,
                  Settings.Secure.BLUETOOTH_HCI_LOG,
-                 Settings.Secure.BRIGHTNESS_USE_TWILIGHT,  // Candidate for backup?
                  Settings.Secure.CARRIER_APPS_HANDLED,
                  Settings.Secure.COMPLETED_CATEGORY_PREFIX,
                  Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
diff --git a/core/tests/coretests/src/android/transition/FadeTransitionTest.java b/core/tests/coretests/src/android/transition/FadeTransitionTest.java
index dc60423..7e7e815 100644
--- a/core/tests/coretests/src/android/transition/FadeTransitionTest.java
+++ b/core/tests/coretests/src/android/transition/FadeTransitionTest.java
@@ -21,7 +21,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.transition.Transition.TransitionListener;
-import android.transition.Transition.TransitionListenerAdapter;
+import android.transition.TransitionListenerAdapter;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
index a73f5a6..44fcd13 100644
--- a/core/tests/coretests/src/android/view/ViewAttachTest.java
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -16,9 +16,17 @@
 
 package android.view;
 
+import android.content.Context;
 import android.content.pm.ActivityInfo;
+import android.graphics.PixelFormat;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.frameworks.coretests.R;
 
 public class ViewAttachTest extends
         ActivityInstrumentationTestCase2<ViewAttachTestActivity> {
@@ -51,4 +59,38 @@
             SystemClock.sleep(250);
         }
     }
+
+    /**
+     * Make sure that on any attached view, if the view is full-screen and hosted
+     * on a round device, the round scrollbars will be displayed even if the activity
+     * window is offset.
+     *
+     * @throws Throwable
+     */
+    @UiThreadTest
+    public void testRoundScrollbars() throws Throwable {
+        final ViewAttachTestActivity activity = getActivity();
+        final View rootView = activity.getWindow().getDecorView();
+        final WindowManager.LayoutParams params =
+            new WindowManager.LayoutParams(
+                rootView.getWidth(),
+                rootView.getHeight(),
+                50, /* xPosition */
+                0, /* yPosition */
+                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+                PixelFormat.TRANSLUCENT);
+
+        rootView.setLayoutParams(params);
+
+        View contentView = activity.findViewById(R.id.view_attach_view);
+        boolean shouldDrawRoundScrollbars = contentView.shouldDrawRoundScrollbar();
+
+        if (activity.getResources().getConfiguration().isScreenRound()) {
+            assertTrue(shouldDrawRoundScrollbars);
+        } else {
+            // Never draw round scrollbars on non-round devices.
+            assertFalse(shouldDrawRoundScrollbars);
+        }
+    }
 }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index e46f166..9cdc660 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -155,6 +155,7 @@
     <assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
     <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
     <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" />
+    <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="cameraserver" />
 
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c5961ab..039ab1f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -132,6 +132,7 @@
         <permission name="android.permission.ACCESS_IMS_CALL_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
+        <permission name="android.permission.BIND_IMS_SERVICE"/>
         <permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
         <permission name="android.permission.CALL_PRIVILEGED"/>
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
@@ -339,4 +340,4 @@
         <permission name="android.permission.CONTROL_VPN"/>
     </privapp-permissions>
 
-</permissions>
\ No newline at end of file
+</permissions>
diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java
index f5cedfa..b490545 100644
--- a/graphics/java/android/graphics/RectF.java
+++ b/graphics/java/android/graphics/RectF.java
@@ -583,4 +583,17 @@
         right = in.readFloat();
         bottom = in.readFloat();
     }
+
+    /**
+     * Scales up the rect by the given scale.
+     * @hide
+     */
+    public void scale(float scale) {
+        if (scale != 1.0f) {
+            left = left * scale;
+            top = top * scale ;
+            right = right * scale;
+            bottom = bottom * scale;
+        }
+    }
 }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 5531871..750ef3f 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -198,9 +198,10 @@
     }
 
     /**
+     * Used by resources for cached loading if the font is available.
      * @hide
      */
-    public static Typeface createFromCache(AssetManager mgr, String path) {
+    public static Typeface findFromCache(AssetManager mgr, String path) {
         synchronized (sDynamicTypefaceCache) {
             final String key = createAssetUid(mgr, path);
             Typeface typeface = sDynamicTypefaceCache.get(key);
@@ -221,6 +222,15 @@
      * @param callback A callback that will be triggered when results are obtained. May not be null.
      */
     public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) {
+        // Check the cache first
+        // TODO: would the developer want to avoid a cache hit and always ask for the freshest
+        // result?
+        Typeface cachedTypeface = findFromCache(
+                request.getProviderAuthority(), request.getQuery());
+        if (cachedTypeface != null) {
+            mHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface));
+            return;
+        }
         synchronized (sLock) {
             if (sFontsContract == null) {
                 sFontsContract = new FontsContract();
@@ -229,20 +239,34 @@
             final ResultReceiver receiver = new ResultReceiver(null) {
                 @Override
                 public void onReceiveResult(int resultCode, Bundle resultData) {
-                    mHandler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            receiveResult(request, callback, resultCode, resultData);
-                        }
-                    });
+                    mHandler.post(() -> receiveResult(request, callback, resultCode, resultData));
                 }
             };
             sFontsContract.getFont(request, receiver);
         }
     }
 
+    private static Typeface findFromCache(String providerAuthority, String query) {
+        synchronized (sDynamicTypefaceCache) {
+            final String key = createProviderUid(providerAuthority, query);
+            Typeface typeface = sDynamicTypefaceCache.get(key);
+            if (typeface != null) {
+                return typeface;
+            }
+        }
+        return null;
+    }
+
     private static void receiveResult(FontRequest request, FontRequestCallback callback,
             int resultCode, Bundle resultData) {
+        Typeface cachedTypeface = findFromCache(
+                request.getProviderAuthority(), request.getQuery());
+        if (cachedTypeface != null) {
+            // We already know the result.
+            // Probably the requester requests the same font again in a short interval.
+            callback.onTypefaceRetrieved(cachedTypeface);
+            return;
+        }
         if (resultCode == FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND) {
             callback.onTypefaceRequestFailed(
                     FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND);
@@ -296,8 +320,12 @@
             }
         }
         fontFamily.freeze();
-        callback.onTypefaceRetrieved(Typeface.createFromFamiliesWithDefault(
-                new FontFamily[] {fontFamily}));
+        Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily });
+        synchronized (sDynamicTypefaceCache) {
+            String key = createProviderUid(request.getProviderAuthority(), request.getQuery());
+            sDynamicTypefaceCache.put(key, typeface);
+        }
+        callback.onTypefaceRetrieved(typeface);
     }
 
     /**
@@ -464,6 +492,7 @@
     private static String createAssetUid(final AssetManager mgr, String path) {
         final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
         final StringBuilder builder = new StringBuilder();
+        builder.append("asset:");
         final int size = pkgs.size();
         for (int i = 0; i < size; i++) {
             builder.append(pkgs.valueAt(i));
@@ -474,6 +503,18 @@
     }
 
     /**
+     * Creates a unique id for a given font provider and query.
+     */
+    private static String createProviderUid(String authority, String query) {
+        final StringBuilder builder = new StringBuilder();
+        builder.append("provider:");
+        builder.append(authority);
+        builder.append("-");
+        builder.append(query);
+        return builder.toString();
+    }
+
+    /**
      * Create a new typeface from the specified font file.
      *
      * @param path The path to the font data.
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index a799fdf..692199d 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -192,7 +192,7 @@
 ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
     hwui_cflags += -DANDROID_ENABLE_RENDERSCRIPT
     hwui_c_includes += \
-        $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,) \
+        $(call intermediates-dir-for,STATIC_LIBRARIES,TARGET,) \
         frameworks/rs/cpp \
         frameworks/rs
 endif
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 1dad58f..71bee93 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -205,6 +205,10 @@
     *d++ = a * (start.g * oppAmount + end.g * amount);
     *d++ = a * (start.b * oppAmount + end.b * amount);
 #else
+    // What we're doing to the alpha channel here is technically incorrect
+    // but reproduces Android's old behavior when the alpha was pre-multiplied
+    // with gamma-encoded colors
+    a = EOCF_sRGB(a);
     *d++ = a * OECF_sRGB(start.r * oppAmount + end.r * amount);
     *d++ = a * OECF_sRGB(start.g * oppAmount + end.g * amount);
     *d++ = a * OECF_sRGB(start.b * oppAmount + end.b * amount);
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 7107679..42ef762 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -164,24 +164,39 @@
 // Dithering must be done in the quantization space
 // When we are writing to an sRGB framebuffer, we must do the following:
 //     EOCF(OECF(color) + dither)
-// We approximate the transfer functions with gamma 2.0 to avoid branches and pow()
 // The dithering pattern is generated with a triangle noise generator in the range [-0.0,1.0]
 // TODO: Handle linear fp16 render targets
-const char* gFS_Gradient_Functions =
-        "\nfloat triangleNoise(const highp vec2 n) {\n"
-        "    highp vec2 p = fract(n * vec2(5.3987, 5.4421));\n"
-        "    p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));\n"
-        "    highp float xy = p.x * p.y;\n"
-        "    return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;\n"
-        "}\n";
+const char* gFS_Gradient_Functions = R"__SHADER__(
+        float triangleNoise(const highp vec2 n) {
+            highp vec2 p = fract(n * vec2(5.3987, 5.4421));
+            p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
+            highp float xy = p.x * p.y;
+            return fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0;
+        }
+
+        float OECF_sRGB(const float linear) {
+            // IEC 61966-2-1:1999
+            return linear <= 0.0031308 ? linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+        }
+
+        vec3 OECF_sRGB(const vec3 linear) {
+            return vec3(OECF_sRGB(linear.r), OECF_sRGB(linear.g), OECF_sRGB(linear.b));
+        }
+
+        float EOCF_sRGB(float srgb) {
+            // IEC 61966-2-1:1999
+            return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+        }
+)__SHADER__";
 const char* gFS_Gradient_Preamble[2] = {
         // Linear framebuffer
         "\nvec4 dither(const vec4 color) {\n"
         "    return vec4(color.rgb + (triangleNoise(gl_FragCoord.xy * screenSize.xy) / 255.0), color.a);\n"
         "}\n"
         "\nvec4 gammaMix(const vec4 a, const vec4 b, float v) {\n"
-        "    vec4 c = pow(mix(a, b, v), vec4(vec3(1.0 / 2.2), 1.0));\n"
-        "    return vec4(c.rgb * c.a, c.a);\n"
+        "    vec4 c = mix(a, b, v);\n"
+        "    c.a = EOCF_sRGB(c.a);\n" // This is technically incorrect but preserves compatibility
+        "    return vec4(OECF_sRGB(c.rgb) * c.a, c.a);\n"
         "}\n",
         // sRGB framebuffer
         "\nvec4 dither(const vec4 color) {\n"
@@ -200,13 +215,15 @@
 // The gamma coefficient is chosen to thicken or thin the text accordingly
 // The dot product used to compute the luminance could be approximated with
 // a simple max(color.r, color.g, color.b)
-const char* gFS_Gamma_Preamble =
-        "\n#define GAMMA (%.2f)\n"
-        "#define GAMMA_INV (%.2f)\n"
-        "\nfloat gamma(float a, const vec3 color) {\n"
-        "    float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));\n"
-        "    return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);\n"
-        "}\n";
+const char* gFS_Gamma_Preamble = R"__SHADER__(
+        #define GAMMA (%.2f)
+        #define GAMMA_INV (%.2f)
+
+        float gamma(float a, const vec3 color) {
+            float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
+            return pow(a, luminance < 0.5 ? GAMMA_INV : GAMMA);
+        }
+)__SHADER__";
 
 const char* gFS_Main =
         "\nvoid main(void) {\n"
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 705395e..f6850a1 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -44,7 +44,7 @@
     case GL_RGBA16F:
         return 8;
     default:
-        LOG_ALWAYS_FATAL("UNKNOWN FORMAT %d", glFormat);
+        LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat);
     }
 }
 
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index 37126a6..f69da48 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -29,5 +29,5 @@
     libandroidfw
 
 ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
-    LOCAL_SHARED_LIBRARIES += libRS libRScpp
+    LOCAL_SHARED_LIBRARIES += libRScpp
 endif
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index d05e7f6..2ead5c5 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -24,6 +24,7 @@
 #include <SkGaussianEdgeShader.h>
 #include <SkPathOps.h>
 #include <SkRRectsGaussianEdgeMaskFilter.h>
+#include <SkShadowUtils.h>
 
 namespace android {
 namespace uirenderer {
@@ -115,498 +116,6 @@
     }
 }
 
-/**
- * @param canvas             the destination for the shadow draws
- * @param shape              the shape casting the shadow
- * @param casterZValue       the Z value of the caster RRect
- * @param ambientAlpha       the maximum alpha value to use when drawing the ambient shadow
- * @param draw               the function used to draw 'shape'
- */
-template <typename Shape, typename F>
-static void DrawAmbientShadowGeneral(SkCanvas* canvas, const Shape& shape, float casterZValue,
-        float ambientAlpha, F&& draw) {
-    if (ambientAlpha <= 0) {
-        return;
-    }
-
-    const float kHeightFactor = 1.f/128.f;
-    const float kGeomFactor = 64;
-
-    float umbraAlpha = 1 / (1 + SkMaxScalar(casterZValue*kHeightFactor, 0));
-    float radius = casterZValue*kHeightFactor*kGeomFactor;
-
-    sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
-            SkBlurMask::ConvertRadiusToSigma(radius), SkBlurMaskFilter::kNone_BlurFlag);
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setMaskFilter(std::move(mf));
-    paint.setARGB(ambientAlpha*umbraAlpha, 0, 0, 0);
-
-    draw(shape, paint);
-}
-
-/**
- * @param canvas             the destination for the shadow draws
- * @param shape              the shape casting the shadow
- * @param casterZValue       the Z value of the caster RRect
- * @param lightPos           the position of the light casting the shadow
- * @param lightWidth
- * @param spotAlpha          the maximum alpha value to use when drawing the spot shadow
- * @param draw               the function used to draw 'shape'
- */
-template <typename Shape, typename F>
-static void DrawSpotShadowGeneral(SkCanvas* canvas, const Shape& shape, float casterZValue,
-        float spotAlpha, F&& draw) {
-    if (spotAlpha <= 0) {
-        return;
-    }
-
-    const Vector3 lightPos = SkiaPipeline::getLightCenter();
-    float zRatio = casterZValue / (lightPos.z - casterZValue);
-    // clamp
-    if (zRatio < 0.0f) {
-        zRatio = 0.0f;
-    } else if (zRatio > 0.95f) {
-        zRatio = 0.95f;
-    }
-
-    float blurRadius = SkiaPipeline::getLightRadius()*zRatio;
-
-    SkAutoCanvasRestore acr(canvas, true);
-
-    sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
-            SkBlurMask::ConvertRadiusToSigma(blurRadius), SkBlurMaskFilter::kNone_BlurFlag);
-
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setMaskFilter(std::move(mf));
-    paint.setARGB(spotAlpha, 0, 0, 0);
-
-    // approximate projection by translating and scaling projected offset of bounds center
-    // TODO: compute the actual 2D projection
-    SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
-    canvas->scale(scale, scale);
-    SkPoint center = SkPoint::Make(shape.getBounds().centerX(), shape.getBounds().centerY());
-    SkMatrix ctmInverse;
-    if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
-        ALOGW("Matrix is degenerate. Will not render shadow!");
-        return;
-    }
-    SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
-    ctmInverse.mapPoints(&lightPos2D, 1);
-    canvas->translate(zRatio*(center.fX - lightPos2D.fX), zRatio*(center.fY - lightPos2D.fY));
-
-    draw(shape, paint);
-}
-
-#define MAX_BLUR_RADIUS 16383.75f
-#define MAX_PAD         64
-
-/**
- * @param casterRect         the rectangle bounds of the RRect casting the shadow
- * @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
- * @param ambientAlpha       the maximum alpha value to use when drawing the ambient shadow
- * @param spotAlpha          the maximum alpha value to use when drawing the spot shadow
- * @param casterAlpha        the alpha value of the RRect casting the shadow (0.0-1.0 range)
- * @param casterZValue       the Z value of the caster RRect
- * @param scaleFactor        the scale needed to map from src-space to device-space
- * @param canvas             the destination for the shadow draws
- */
-static void DrawRRectShadows(const SkRect& casterRect, SkScalar casterCornerRadius,
-        SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue,
-        SkScalar scaleFactor, SkCanvas* canvas) {
-    SkASSERT(casterCornerRadius >= 0.0f);
-
-    // For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space
-    const SkScalar minRadius = 0.5f / scaleFactor;
-
-    const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
-            SkScalarHalf(casterRect.height()));
-    const bool isRect = casterCornerRadius <= minRadius;
-
-    sk_sp<SkShader> edgeShader(SkGaussianEdgeShader::Make());
-
-    if (ambientAlpha > 0.0f) {
-        static const float kHeightFactor = 1.0f / 128.0f;
-        static const float kGeomFactor = 64.0f;
-
-        SkScalar srcSpaceAmbientRadius = casterZValue * kHeightFactor * kGeomFactor;
-        // the device-space radius sent to the blur shader must fit in 14.2 fixed point
-        if (srcSpaceAmbientRadius*scaleFactor > MAX_BLUR_RADIUS) {
-            srcSpaceAmbientRadius = MAX_BLUR_RADIUS/scaleFactor;
-        }
-        const float umbraAlpha = 1.0f / (1.0f + std::max(casterZValue * kHeightFactor, 0.0f));
-        const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
-
-        // For the ambient rrect, we inset the offset rect by half the srcSpaceAmbientRadius
-        // to get our stroke shape.
-        SkScalar ambientPathOutset = std::max(ambientOffset - srcSpaceAmbientRadius * 0.5f,
-                minRadius);
-
-        SkRRect ambientRRect;
-        const SkRect temp = casterRect.makeOutset(ambientPathOutset, ambientPathOutset);
-        if (isOval) {
-            ambientRRect = SkRRect::MakeOval(temp);
-        } else if (isRect) {
-            ambientRRect = SkRRect::MakeRectXY(temp, ambientPathOutset, ambientPathOutset);
-        } else {
-            ambientRRect = SkRRect::MakeRectXY(temp, casterCornerRadius + ambientPathOutset,
-                    casterCornerRadius + ambientPathOutset);
-        }
-
-        SkPaint paint;
-        paint.setAntiAlias(true);
-        paint.setStyle(SkPaint::kStroke_Style);
-        // we outset the stroke a little to cover up AA on the interior edge
-        float pad = 0.5f;
-        paint.setStrokeWidth(srcSpaceAmbientRadius + 2.0f * pad);
-        // handle scale of radius and pad due to CTM
-        pad *= scaleFactor;
-        const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
-        SkASSERT(devSpaceAmbientRadius <= MAX_BLUR_RADIUS);
-        SkASSERT(pad < MAX_PAD);
-        // convert devSpaceAmbientRadius to 14.2 fixed point and place in the R & G components
-        // convert pad to 6.2 fixed point and place in the B component
-        uint16_t iDevSpaceAmbientRadius = (uint16_t)(4.0f * devSpaceAmbientRadius);
-        paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, iDevSpaceAmbientRadius >> 8,
-                iDevSpaceAmbientRadius & 0xff, (unsigned char)(4.0f * pad)));
-
-        paint.setShader(edgeShader);
-        canvas->drawRRect(ambientRRect, paint);
-    }
-
-    if (spotAlpha > 0.0f) {
-        const Vector3 lightPos = SkiaPipeline::getLightCenter();
-        float zRatio = casterZValue / (lightPos.z - casterZValue);
-        // clamp
-        if (zRatio < 0.0f) {
-            zRatio = 0.0f;
-        } else if (zRatio > 0.95f) {
-            zRatio = 0.95f;
-        }
-
-        const SkScalar lightWidth = SkiaPipeline::getLightRadius();
-        SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
-        // the device-space radius sent to the blur shader must fit in 14.2 fixed point
-        if (srcSpaceSpotRadius*scaleFactor > MAX_BLUR_RADIUS) {
-            srcSpaceSpotRadius = MAX_BLUR_RADIUS/scaleFactor;
-        }
-
-        SkRRect spotRRect;
-        if (isOval) {
-            spotRRect = SkRRect::MakeOval(casterRect);
-        } else if (isRect) {
-            spotRRect = SkRRect::MakeRectXY(casterRect, minRadius, minRadius);
-        } else {
-            spotRRect = SkRRect::MakeRectXY(casterRect, casterCornerRadius, casterCornerRadius);
-        }
-
-        SkRRect spotShadowRRect;
-        // Compute the scale and translation for the spot shadow.
-        const SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
-        spotRRect.transform(SkMatrix::MakeScale(scale, scale), &spotShadowRRect);
-
-        SkPoint center = SkPoint::Make(spotShadowRRect.rect().centerX(),
-                                       spotShadowRRect.rect().centerY());
-        SkMatrix ctmInverse;
-        if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
-            ALOGW("Matrix is degenerate. Will not render spot shadow!");
-            return;
-        }
-        SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
-        ctmInverse.mapPoints(&lightPos2D, 1);
-        const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
-                zRatio*(center.fY - lightPos2D.fY));
-
-        SkAutoCanvasRestore acr(canvas, true);
-
-        // We want to extend the stroked area in so that it meets up with the caster
-        // geometry. The stroked geometry will, by definition already be inset half the
-        // stroke width but we also have to account for the scaling.
-        // We also add 1/2 to cover up AA on the interior edge.
-        SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(casterRect.fLeft),
-                SkTAbs(casterRect.fRight)), SkTMax(SkTAbs(casterRect.fTop),
-                SkTAbs(casterRect.fBottom)));
-        SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) +
-                scaleOffset + 0.5f;
-
-        // Compute area
-        SkScalar strokeWidth = srcSpaceSpotRadius + insetAmount;
-        SkScalar strokedArea = 2.0f*strokeWidth * (spotShadowRRect.width()
-                + spotShadowRRect.height());
-        SkScalar filledArea = (spotShadowRRect.height() + srcSpaceSpotRadius)
-                * (spotShadowRRect.width() + srcSpaceSpotRadius);
-
-        SkPaint paint;
-        paint.setAntiAlias(true);
-
-        // If the area of the stroked geometry is larger than the fill geometry, just fill it.
-        if (strokedArea > filledArea || casterAlpha < 1.0f || insetAmount < 0.0f) {
-            paint.setStyle(SkPaint::kStrokeAndFill_Style);
-            paint.setStrokeWidth(srcSpaceSpotRadius);
-        } else {
-            // Since we can't have unequal strokes, inset the shadow rect so the inner
-            // and outer edges of the stroke will land where we want.
-            SkRect insetRect = spotShadowRRect.rect().makeInset(insetAmount/2.0f, insetAmount/2.0f);
-            SkScalar insetRad = SkTMax(spotShadowRRect.getSimpleRadii().fX - insetAmount/2.0f,
-                    minRadius);
-            spotShadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
-            paint.setStyle(SkPaint::kStroke_Style);
-            paint.setStrokeWidth(strokeWidth);
-        }
-
-        // handle scale of radius and pad due to CTM
-        const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
-        SkASSERT(devSpaceSpotRadius <= MAX_BLUR_RADIUS);
-
-        const SkScalar devSpaceSpotPad = 0;
-        SkASSERT(devSpaceSpotPad < MAX_PAD);
-
-        // convert devSpaceSpotRadius to 14.2 fixed point and place in the R & G
-        // components convert devSpaceSpotPad to 6.2 fixed point and place in the B component
-        uint16_t iDevSpaceSpotRadius = (uint16_t)(4.0f * devSpaceSpotRadius);
-        paint.setColor(SkColorSetARGB((unsigned char) spotAlpha, iDevSpaceSpotRadius >> 8,
-                iDevSpaceSpotRadius & 0xff, (unsigned char)(4.0f * devSpaceSpotPad)));
-        paint.setShader(edgeShader);
-
-        canvas->translate(spotOffset.fX, spotOffset.fY);
-        canvas->drawRRect(spotShadowRRect, paint);
-    }
-}
-
-/**
- * @param casterRect         the rectangle bounds of the RRect casting the shadow
- * @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
- * @param ambientAlpha       the maximum alpha value to use when drawing the ambient shadow
- * @param spotAlpha          the maximum alpha value to use when drawing the spot shadow
- * @param casterZValue       the Z value of the caster RRect
- * @param scaleFactor        the scale needed to map from src-space to device-space
- * @param clipRR             the oval or rect with which the drawn roundrect must be intersected
- * @param canvas             the destination for the shadow draws
- */
-static void DrawRRectShadowsWithClip(const SkRect& casterRect, SkScalar casterCornerRadius,
-        SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterZValue, SkScalar scaleFactor,
-        const SkRRect& clipRR, SkCanvas* canvas) {
-    SkASSERT(casterCornerRadius >= 0.0f);
-
-    const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
-            SkScalarHalf(casterRect.height()));
-
-    if (ambientAlpha > 0.0f) {
-        static const float kHeightFactor = 1.0f / 128.0f;
-        static const float kGeomFactor = 64.0f;
-
-        const SkScalar srcSpaceAmbientRadius = casterZValue * kHeightFactor * kGeomFactor;
-        const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
-
-        const float umbraAlpha = 1.0f / (1.0f + std::max(casterZValue * kHeightFactor, 0.0f));
-        const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
-
-        const SkRect srcSpaceAmbientRect = casterRect.makeOutset(ambientOffset, ambientOffset);
-        SkRect devSpaceAmbientRect;
-        canvas->getTotalMatrix().mapRect(&devSpaceAmbientRect, srcSpaceAmbientRect);
-
-        SkRRect devSpaceAmbientRRect;
-        if (isOval) {
-            devSpaceAmbientRRect = SkRRect::MakeOval(devSpaceAmbientRect);
-        } else {
-            const SkScalar devSpaceCornerRadius = scaleFactor * (casterCornerRadius + ambientOffset);
-            devSpaceAmbientRRect = SkRRect::MakeRectXY(devSpaceAmbientRect, devSpaceCornerRadius,
-                    devSpaceCornerRadius);
-        }
-
-        const SkRect srcSpaceAmbClipRect = clipRR.rect().makeOutset(ambientOffset, ambientOffset);
-        SkRect devSpaceAmbClipRect;
-        canvas->getTotalMatrix().mapRect(&devSpaceAmbClipRect, srcSpaceAmbClipRect);
-        SkRRect devSpaceAmbientClipRR;
-        if (clipRR.isOval()) {
-            devSpaceAmbientClipRR = SkRRect::MakeOval(devSpaceAmbClipRect);
-        } else {
-            SkASSERT(clipRR.isRect());
-            devSpaceAmbientClipRR = SkRRect::MakeRect(devSpaceAmbClipRect);
-        }
-
-        SkRect cover = srcSpaceAmbClipRect;
-        if (!cover.intersect(srcSpaceAmbientRect)) {
-            return;
-        }
-
-        SkPaint paint;
-        paint.setColor(SkColorSetARGB((unsigned char) ambientAlpha, 0, 0, 0));
-        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceAmbientRRect,
-            devSpaceAmbientClipRR, devSpaceAmbientRadius));
-        canvas->drawRect(cover, paint);
-    }
-
-    if (spotAlpha > 0.0f) {
-        const Vector3 lightPos = SkiaPipeline::getLightCenter();
-        float zRatio = casterZValue / (lightPos.z - casterZValue);
-        // clamp
-        if (zRatio < 0.0f) {
-            zRatio = 0.0f;
-        } else if (zRatio > 0.95f) {
-            zRatio = 0.95f;
-        }
-
-        const SkScalar lightWidth = SkiaPipeline::getLightRadius();
-        const SkScalar srcSpaceSpotRadius = 2.0f * lightWidth * zRatio;
-        const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
-
-        // Compute the scale and translation for the spot shadow.
-        const SkScalar scale = lightPos.z / (lightPos.z - casterZValue);
-        const SkMatrix spotMatrix = SkMatrix::MakeScale(scale, scale);
-
-        SkRect srcSpaceScaledRect = casterRect;
-        spotMatrix.mapRect(&srcSpaceScaledRect);
-        srcSpaceScaledRect.outset(SkScalarHalf(srcSpaceSpotRadius),
-                SkScalarHalf(srcSpaceSpotRadius));
-
-        SkRRect srcSpaceSpotRRect;
-        if (isOval) {
-            srcSpaceSpotRRect = SkRRect::MakeOval(srcSpaceScaledRect);
-        } else {
-            srcSpaceSpotRRect = SkRRect::MakeRectXY(srcSpaceScaledRect, casterCornerRadius * scale,
-                    casterCornerRadius * scale);
-        }
-
-        SkPoint center = SkPoint::Make(srcSpaceSpotRRect.rect().centerX(),
-                srcSpaceSpotRRect.rect().centerY());
-        SkMatrix ctmInverse;
-        if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
-            ALOGW("Matrix is degenerate. Will not render spot shadow!");
-            return;
-        }
-        SkPoint lightPos2D = SkPoint::Make(lightPos.x, lightPos.y);
-        ctmInverse.mapPoints(&lightPos2D, 1);
-        const SkPoint spotOffset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
-                zRatio*(center.fY - lightPos2D.fY));
-
-        SkAutoCanvasRestore acr(canvas, true);
-        canvas->translate(spotOffset.fX, spotOffset.fY);
-
-        SkRect devSpaceScaledRect;
-        canvas->getTotalMatrix().mapRect(&devSpaceScaledRect, srcSpaceScaledRect);
-
-        SkRRect devSpaceSpotRRect;
-        if (isOval) {
-            devSpaceSpotRRect = SkRRect::MakeOval(devSpaceScaledRect);
-        } else {
-            const SkScalar devSpaceScaledCornerRadius = casterCornerRadius * scale * scaleFactor;
-            devSpaceSpotRRect = SkRRect::MakeRectXY(devSpaceScaledRect, devSpaceScaledCornerRadius,
-                    devSpaceScaledCornerRadius);
-        }
-
-        SkPaint paint;
-        paint.setColor(SkColorSetARGB((unsigned char) spotAlpha, 0, 0, 0));
-
-        SkRect srcSpaceScaledClipRect = clipRR.rect();
-        spotMatrix.mapRect(&srcSpaceScaledClipRect);
-        srcSpaceScaledClipRect.outset(SkScalarHalf(srcSpaceSpotRadius),
-                SkScalarHalf(srcSpaceSpotRadius));
-
-        SkRect devSpaceScaledClipRect;
-        canvas->getTotalMatrix().mapRect(&devSpaceScaledClipRect, srcSpaceScaledClipRect);
-        SkRRect devSpaceSpotClipRR;
-        if (clipRR.isOval()) {
-            devSpaceSpotClipRR = SkRRect::MakeOval(devSpaceScaledClipRect);
-        } else {
-            SkASSERT(clipRR.isRect());
-            devSpaceSpotClipRR = SkRRect::MakeRect(devSpaceScaledClipRect);
-        }
-
-        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceSpotRRect,
-            devSpaceSpotClipRR, devSpaceSpotRadius));
-
-        SkRect cover = srcSpaceScaledClipRect;
-        if (!cover.intersect(srcSpaceSpotRRect.rect())) {
-            return;
-        }
-
-        canvas->drawRect(cover, paint);
-    }
-}
-
-/**
- * @param casterRect         the rectangle bounds of the RRect casting the shadow
- * @param casterCornerRadius the x&y radius for all the corners of the RRect casting the shadow
- * @param casterClipRect     a rectangular clip that must be intersected with the
- *                           shadow-casting RRect prior to casting the shadow
- * @param revealClip         a circular clip that must be interested with the castClipRect
- *                           and the shadow-casting rect prior to casting the shadow
- * @param ambientAlpha       the maximum alpha value to use when drawing the ambient shadow
- * @param spotAlpha          the maximum alpha value to use when drawing the spot shadow
- * @param casterAlpha        the alpha value of the RRect casting the shadow (0.0-1.0 range)
- * @param casterZValue       the Z value of the caster RRect
- * @param canvas             the destination for the shadow draws
- *
- * We have special cases for 4 round rect shadow draws:
- *    1) a RRect clipped by a reveal animation
- *    2) a RRect clipped by a rectangle
- *    3) an unclipped RRect with non-uniform scale
- *    4) an unclipped RRect with uniform scale
- * 1,2 and 4 require that the scale is uniform.
- * 1 and 2 require that rects stay rects.
- */
-static bool DrawShadowsAsRRects(const SkRect& casterRect, SkScalar casterCornerRadius,
-        const SkRect& casterClipRect, const RevealClip& revealClip, SkScalar ambientAlpha,
-        SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue, SkCanvas* canvas) {
-    SkScalar scaleFactors[2];
-    if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
-        ALOGW("Matrix is degenerate. Will not render shadow!");
-        return false;
-    }
-
-    // The casterClipRect will be empty when bounds clipping is disabled
-    bool casterIsClippedByRect = !casterClipRect.isEmpty();
-    bool uniformScale = scaleFactors[0] == scaleFactors[1];
-
-    if (revealClip.willClip()) {
-        if (casterIsClippedByRect || !uniformScale || !canvas->getTotalMatrix().rectStaysRect()) {
-            return false;  // Fall back to the slow path since PathOps are required
-        }
-
-        const float revealRadius = revealClip.getRadius();
-        SkRect revealClipRect = SkRect::MakeLTRB(revealClip.getX()-revealRadius,
-                revealClip.getY()-revealRadius, revealClip.getX()+revealRadius,
-                revealClip.getY()+revealRadius);
-        SkRRect revealClipRR = SkRRect::MakeOval(revealClipRect);
-
-        DrawRRectShadowsWithClip(casterRect, casterCornerRadius, ambientAlpha, spotAlpha,
-                casterZValue, scaleFactors[0], revealClipRR, canvas);
-        return true;
-    }
-
-    if (casterIsClippedByRect) {
-        if (!uniformScale || !canvas->getTotalMatrix().rectStaysRect()) {
-            return false;  // Fall back to the slow path since PathOps are required
-        }
-
-        SkRRect casterClipRR = SkRRect::MakeRect(casterClipRect);
-
-        DrawRRectShadowsWithClip(casterRect, casterCornerRadius, ambientAlpha, spotAlpha,
-                casterZValue, scaleFactors[0], casterClipRR, canvas);
-        return true;
-    }
-
-    // The fast path needs uniform scale
-    if (!uniformScale) {
-        SkRRect casterRR = SkRRect::MakeRectXY(casterRect, casterCornerRadius, casterCornerRadius);
-        DrawAmbientShadowGeneral(canvas, casterRR, casterZValue, ambientAlpha,
-                [&](const SkRRect& rrect, const SkPaint& paint) {
-                    canvas->drawRRect(rrect, paint);
-                });
-        DrawSpotShadowGeneral(canvas, casterRR, casterZValue, spotAlpha,
-                [&](const SkRRect& rrect, const SkPaint& paint) {
-                canvas->drawRRect(rrect, paint);
-                });
-        return true;
-    }
-
-    DrawRRectShadows(casterRect, casterCornerRadius, ambientAlpha, spotAlpha, casterAlpha,
-            casterZValue, scaleFactors[0], canvas);
-    return true;
-}
-
 // copied from FrameBuilder::deferShadow
 void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* caster) {
     const RenderProperties& casterProperties = caster->getNodeProperties();
@@ -626,8 +135,8 @@
         return;
     }
 
-    float ambientAlpha = SkiaPipeline::getAmbientShadowAlpha()*casterAlpha;
-    float spotAlpha = SkiaPipeline::getSpotShadowAlpha()*casterAlpha;
+    float ambientAlpha = (SkiaPipeline::getAmbientShadowAlpha()/255.f)*casterAlpha;
+    float spotAlpha = (SkiaPipeline::getSpotShadowAlpha()/255.f)*casterAlpha;
     const float casterZValue = casterProperties.getZ();
 
     const RevealClip& revealClip = casterProperties.getRevealClip();
@@ -659,19 +168,7 @@
     hwuiMatrix.copyTo(shadowMatrix);
     canvas->concat(shadowMatrix);
 
-    const Outline& casterOutline = casterProperties.getOutline();
-    Rect possibleRect;
-    float radius;
-    if (casterOutline.getAsRoundRect(&possibleRect, &radius)) {
-        if (DrawShadowsAsRRects(possibleRect.toSkRect(), radius, casterClipRect, revealClip,
-                ambientAlpha, spotAlpha, casterAlpha, casterZValue, canvas)) {
-            return;
-        }
-    }
-
-    // Hard cases and calls to general shadow code
     const SkPath* casterOutlinePath = casterProperties.getOutline().getPath();
-
     // holds temporary SkPath to store the result of intersections
     SkPath tmpPath;
     const SkPath* casterPath = casterOutlinePath;
@@ -691,16 +188,11 @@
         Op(*casterPath, clipBoundsPath, kIntersect_SkPathOp, &tmpPath);
         casterPath = &tmpPath;
     }
-
-    DrawAmbientShadowGeneral(canvas, *casterPath, casterZValue, ambientAlpha,
-            [&](const SkPath& path, const SkPaint& paint) {
-                canvas->drawPath(path, paint);
-            });
-
-    DrawSpotShadowGeneral(canvas, *casterPath, casterZValue, spotAlpha,
-            [&](const SkPath& path, const SkPaint& paint) {
-                canvas->drawPath(path, paint);
-            });
+    const Vector3 lightPos = SkiaPipeline::getLightCenter();
+    SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
+    SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
+            SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
+            casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
 }
 
 }; // namespace skiapipeline
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 0d567f7..7dfc2ee 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -80,6 +80,7 @@
     delete mStencil;
     mStencil = nullptr;
 
+    destroyLayersInUpdater();
     GpuMemoryTracker::onGpuContextDestroyed();
 }
 
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index a44fa9d..f78bf7a 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -99,8 +99,6 @@
         mActiveLayerUpdaters.erase(layerUpdater);
     }
 
-    void destroyLayersInUpdater();
-
     // TODO: This system is a little clunky feeling, this could use some
     // more thinking...
     void postDecStrong(VirtualLightRefBase* object);
@@ -121,6 +119,7 @@
 private:
     void interruptForFunctorInvoke();
     void resumeFromFunctorInvoke();
+    void destroyLayersInUpdater();
 
     explicit RenderState(renderthread::RenderThread& thread);
     ~RenderState();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5a7de1d..a53e5e0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -570,7 +570,6 @@
         }
         mRenderPipeline->onDestroyHardwareResources();
     }
-    mRenderThread.renderState().destroyLayersInUpdater();
 }
 
 void CanvasContext::trimMemory(RenderThread& thread, int level) {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 454ce4d..c2c2f22 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -603,6 +603,11 @@
 }
 
 void VulkanManager::swapBuffers(VulkanSurface* surface) {
+    if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
+        ATRACE_NAME("Finishing GPU work");
+        mDeviceWaitIdle(mBackendContext->fDevice);
+    }
+
     VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
             surface->mCurrentBackbufferIndex;
     GrVkImageInfo* imageInfo;
diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
new file mode 100644
index 0000000..a63a585
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#include "TestSceneBase.h"
+
+#include <SkColorMatrixFilter.h>
+#include <SkGradientShader.h>
+
+class SimpleColorMatrixAnimation;
+
+static TestScene::Registrar _SimpleColorMatrix(TestScene::Info{
+    "simpleColorMatrix",
+    "A color matrix shader benchmark for the simple scale/translate case, which has R, G, and B "
+    "all scaled and translated the same amount.",
+    TestScene::simpleCreateScene<SimpleColorMatrixAnimation>
+});
+
+class SimpleColorMatrixAnimation : public TestScene {
+public:
+    std::vector< sp<RenderNode> > cards;
+    void createContent(int width, int height, Canvas& canvas) override {
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+
+        sp<RenderNode> card = createCard(0, 0, width, height);
+        canvas.drawRenderNode(card.get());
+        cards.push_back(card);
+    }
+    void doFrame(int frameNr) override {
+        int curFrame = frameNr % 20;
+        for (size_t ci = 0; ci < cards.size(); ci++) {
+            cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+            cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+            cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+        }
+    }
+private:
+    sp<RenderNode> createCard(int x, int y, int width, int height) {
+        return TestUtils::createNode(x, y, x + width, y + height,
+                [width, height](RenderProperties& props, Canvas& canvas) {
+            SkPaint paint;
+            float matrix[20] = { 0 };
+
+            // Simple scale/translate case where R, G, and B are all treated equivalently
+            matrix[SkColorMatrix::kR_Scale] = 1.1f;
+            matrix[SkColorMatrix::kG_Scale] = 1.1f;
+            matrix[SkColorMatrix::kB_Scale] = 1.1f;
+            matrix[SkColorMatrix::kA_Scale] = 0.5f;
+
+            matrix[SkColorMatrix::kR_Trans] = 5.0f;
+            matrix[SkColorMatrix::kG_Trans] = 5.0f;
+            matrix[SkColorMatrix::kB_Trans] = 5.0f;
+            matrix[SkColorMatrix::kA_Trans] = 10.0f;
+
+            paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
+
+            // set a shader so it's not likely for the matrix to be optimized away (since a clever
+            // enough renderer might apply it directly to the paint color)
+            float pos[] = { 0, 1 };
+            SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(width, height) };
+            SkColor colors[2] = { Color::DeepPurple_500, Color::DeepOrange_500 };
+            paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2,
+                SkShader::kClamp_TileMode));
+
+            // overdraw several times to emphasize shader cost
+            for (int i = 0; i < 10; i++) {
+                canvas.drawRect(i, i, width, height, paint);
+            }
+        });
+    }
+};
diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
new file mode 100644
index 0000000..053eb6d
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+
+#include "TestSceneBase.h"
+
+#include <SkGradientShader.h>
+
+class SimpleGradientAnimation;
+
+static TestScene::Registrar _SimpleGradient(TestScene::Info{
+    "simpleGradient",
+    "A benchmark of shader performance of linear, 2 color gradients with black in them.",
+    TestScene::simpleCreateScene<SimpleGradientAnimation>
+});
+
+class SimpleGradientAnimation : public TestScene {
+public:
+    std::vector< sp<RenderNode> > cards;
+    void createContent(int width, int height, Canvas& canvas) override {
+        canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+
+        sp<RenderNode> card = createCard(0, 0, width, height);
+        canvas.drawRenderNode(card.get());
+        cards.push_back(card);
+    }
+    void doFrame(int frameNr) override {
+        int curFrame = frameNr % 20;
+        for (size_t ci = 0; ci < cards.size(); ci++) {
+            cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+            cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+            cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+        }
+    }
+private:
+    sp<RenderNode> createCard(int x, int y, int width, int height) {
+        return TestUtils::createNode(x, y, x + width, y + height,
+                [width, height](RenderProperties& props, Canvas& canvas) {
+            float pos[] = { 0, 1 };
+            SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(width, height) };
+            SkPaint paint;
+            // overdraw several times to emphasize shader cost
+            for (int i = 0; i < 10; i++) {
+                // use i%2 start position to pick 2 color combo with black in it
+                SkColor colors[3] = { Color::Transparent, Color::Black, Color::Cyan_500 };
+                paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2,
+                    SkShader::kClamp_TileMode));
+                canvas.drawRect(i, i, width, height, paint);
+            }
+        });
+    }
+};
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 391a905..ce58a9c 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -913,13 +913,13 @@
         }
     }
     /**
-     * @hide
-     * CANDIDATE FOR PUBLIC (or at least SYSTEM) API
      * Returns the stream type matching the given attributes for volume control.
      * Use this method to derive the stream type needed to configure the volume
-     * control slider in an {@link Activity} with {@link Activity#setVolumeControlStream(int)}.
+     * control slider in an {@link android.app.Activity} with
+     * {@link android.app.Activity#setVolumeControlStream(int)}.
      * <BR>Do not use this method to set the stream type on an audio player object
-     * (e.g. {@link AudioTrack}, {@link MediaPlayer}), use <code>AudioAttributes</code> instead.
+     * (e.g. {@link AudioTrack}, {@link MediaPlayer}) as this is deprecated,
+     * use <code>AudioAttributes</code> instead.
      * @param aa non-null AudioAttributes.
      * @return a valid stream type for <code>Activity</code> or stream volume control that matches
      *     the attributes, or {@link AudioManager#USE_DEFAULT_STREAM_TYPE} if there isn't a direct
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index cd38b50..9083c16 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1956,7 +1956,13 @@
                         e.printStackTrace();
                     }
                     baseSetStartDelayMs(0);
-                    startImpl();
+                    try {
+                        startImpl();
+                    } catch (IllegalStateException e) {
+                        // fail silently for a state exception when it is happening after
+                        // a delayed start, as the player state could have changed between the
+                        // call to start() and the execution of startImpl()
+                    }
                 }
             }.start();
         }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 03dc2ea..1a1d0f3 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1258,7 +1258,13 @@
                         e.printStackTrace();
                     }
                     baseSetStartDelayMs(0);
-                    startImpl();
+                    try {
+                        startImpl();
+                    } catch (IllegalStateException e) {
+                        // fail silently for a state exception when it is happening after
+                        // a delayed start, as the player state could have changed between the
+                        // call to start() and the execution of startImpl()
+                    }
                 }
             }.start();
         }
diff --git a/media/java/android/media/session/IOnMediaKeyListener.aidl b/media/java/android/media/session/IOnMediaKeyListener.aidl
index 7752357..aa98ea3 100644
--- a/media/java/android/media/session/IOnMediaKeyListener.aidl
+++ b/media/java/android/media/session/IOnMediaKeyListener.aidl
@@ -22,7 +22,7 @@
  * Listener to handle media key.
  * @hide
  */
-interface IOnMediaKeyListener {
+oneway interface IOnMediaKeyListener {
     void onMediaKey(in KeyEvent event, in ResultReceiver result);
 }
 
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 2f6e260..a146c62 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -16,6 +16,7 @@
 package android.media.session;
 
 import android.content.Intent;
+import android.media.MediaDescription;
 import android.media.Rating;
 import android.net.Uri;
 import android.os.Bundle;
@@ -49,6 +50,10 @@
     void onRepeatMode(int repeatMode);
     void onShuffleMode(boolean enabled);
     void onCustomAction(String action, in Bundle args);
+    void onAddQueueItem(in MediaDescription description);
+    void onAddQueueItemAt(in MediaDescription description, int index);
+    void onRemoveQueueItem(in MediaDescription description);
+    void onRemoveQueueItemAt(int index);
 
     // These callbacks are for volume handling
     void onAdjustVolume(int direction);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index e92758c..7b5233a 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -18,6 +18,7 @@
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
+import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.session.ISessionControllerCallback;
@@ -51,6 +52,11 @@
     MediaMetadata getMetadata();
     PlaybackState getPlaybackState();
     ParceledListSlice getQueue();
+    void addQueueItem(in MediaDescription description);
+    void addQueueItemAt(in MediaDescription description, int index);
+    void removeQueueItem(in MediaDescription description);
+    void removeQueueItemAt(int index);
+
     CharSequence getQueueTitle();
     Bundle getExtras();
     int getRatingType();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 8cbf8e1..bab2af2 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -23,6 +23,7 @@
 import android.content.pm.ParceledListSlice;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
+import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -38,6 +39,7 @@
 import android.view.KeyEvent;
 
 import java.lang.ref.WeakReference;
+import java.lang.UnsupportedOperationException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -111,8 +113,7 @@
     }
 
     /**
-     * Get a {@link TransportControls} instance to send transport actions to
-     * the associated session.
+     * Get a {@link TransportControls} instance to send transport actions to this session.
      *
      * @return A transport controls instance.
      */
@@ -151,7 +152,7 @@
         try {
             return mSessionBinder.getPlaybackState();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getPlaybackState.", e);
+            Log.wtf(TAG, "Error calling getPlaybackState", e);
             return null;
         }
     }
@@ -165,7 +166,7 @@
         try {
             return mSessionBinder.getMetadata();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getMetadata.", e);
+            Log.wtf(TAG, "Error calling getMetadata", e);
             return null;
         }
     }
@@ -183,12 +184,103 @@
                 return queue.getList();
             }
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getQueue.", e);
+            Log.wtf(TAG, "Error calling getQueue", e);
         }
         return null;
     }
 
     /**
+     * Add a queue item from the given {@code description} at the end of the play queue
+     * of this session. Not all sessions may support this.
+     *
+     * @param description The {@link MediaDescription} for creating the
+     *                    {@link MediaSession.QueueItem} to be inserted.
+     * @throws UnsupportedOperationException If this session doesn't support this.
+     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+     */
+    public void addQueueItem(MediaDescription description) {
+        try {
+            long flags = mSessionBinder.getFlags();
+            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+                throw new UnsupportedOperationException(
+                        "This session doesn't support queue management operations");
+            }
+            mSessionBinder.addQueueItem(description);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error calling addQueueItem", e);
+        }
+    }
+
+    /**
+     * Add a queue item from the given {@code description} at the specified position
+     * in the play queue of this session. Shifts the queue item currently at that position
+     * (if any) and any subsequent queue items to the right (adds one to their indices).
+     * Not all sessions may support this.
+     *
+     * @param description The {@link MediaDescription} for creating the
+     *                    {@link MediaSession.QueueItem} to be inserted.
+     * @param index The index at which the created {@link MediaSession.QueueItem} is to be inserted.
+     * @throws UnsupportedOperationException If this session doesn't support this.
+     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+     */
+    public void addQueueItem(MediaDescription description, int index) {
+        try {
+            long flags = mSessionBinder.getFlags();
+            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+                throw new UnsupportedOperationException(
+                        "This session doesn't support queue management operations");
+            }
+            mSessionBinder.addQueueItemAt(description, index);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error calling addQueueItemAt", e);
+        }
+    }
+
+    /**
+     * Remove the first occurrence of the specified {@link MediaSession.QueueItem}
+     * with the given {@link MediaDescription description} in the play queue of the associated
+     * session. Not all sessions may support this.
+     *
+     * @param description The {@link MediaDescription} for denoting the
+     *                    {@link MediaSession.QueueItem} to be removed.
+     * @throws UnsupportedOperationException If this session doesn't support this.
+     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+     */
+    public void removeQueueItem(MediaDescription description) {
+        try {
+            long flags = mSessionBinder.getFlags();
+            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+                throw new UnsupportedOperationException(
+                        "This session doesn't support queue management operations");
+            }
+            mSessionBinder.removeQueueItem(description);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error calling removeQueueItem", e);
+        }
+    }
+
+    /**
+     * Remove an queue item at the specified position in the play queue
+     * of this session. Not all sessions may support this.
+     *
+     * @param index The index of the element to be removed.
+     * @throws UnsupportedOperationException If this session doesn't support this.
+     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
+     */
+    public void removeQueueItemAt(int index) {
+        try {
+            long flags = mSessionBinder.getFlags();
+            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
+                throw new UnsupportedOperationException(
+                        "This session doesn't support queue management operations");
+            }
+            mSessionBinder.removeQueueItemAt(index);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error calling removeQueueItemAt", e);
+        }
+    }
+
+    /**
      * Get the queue title for this session.
      */
     public @Nullable CharSequence getQueueTitle() {
@@ -230,7 +322,7 @@
         try {
             return mSessionBinder.getRatingType();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getRatingType.", e);
+            Log.wtf(TAG, "Error calling getRatingType", e);
             return Rating.RATING_NONE;
         }
     }
@@ -245,7 +337,7 @@
         try {
             return mSessionBinder.getRepeatMode();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getRepeatMode.", e);
+            Log.wtf(TAG, "Error calling getRepeatMode", e);
             return PlaybackState.REPEAT_MODE_NONE;
         }
     }
@@ -259,7 +351,7 @@
         try {
             return mSessionBinder.isShuffleModeEnabled();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling isShuffleModeEnabled.", e);
+            Log.wtf(TAG, "Error calling isShuffleModeEnabled", e);
             return false;
         }
     }
@@ -273,7 +365,7 @@
         try {
             return mSessionBinder.getFlags();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getFlags.", e);
+            Log.wtf(TAG, "Error calling getFlags", e);
         }
         return 0;
     }
@@ -290,7 +382,7 @@
                     result.maxVolume, result.currentVolume);
 
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getAudioInfo.", e);
+            Log.wtf(TAG, "Error calling getAudioInfo", e);
         }
         return null;
     }
@@ -305,7 +397,7 @@
         try {
             return mSessionBinder.getLaunchPendingIntent();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getPendingIntent.", e);
+            Log.wtf(TAG, "Error calling getPendingIntent", e);
         }
         return null;
     }
@@ -334,7 +426,7 @@
         try {
             mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName());
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling setVolumeTo.", e);
+            Log.wtf(TAG, "Error calling setVolumeTo", e);
         }
     }
 
@@ -355,7 +447,7 @@
         try {
             mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName());
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
+            Log.wtf(TAG, "Error calling adjustVolumeBy", e);
         }
     }
 
@@ -421,7 +513,7 @@
         try {
             mSessionBinder.sendCommand(command, args, cb);
         } catch (RemoteException e) {
-            Log.d(TAG, "Dead object in sendCommand.", e);
+            Log.d(TAG, "Dead object in sendCommand", e);
         }
     }
 
@@ -435,7 +527,7 @@
             try {
                 mPackageName = mSessionBinder.getPackageName();
             } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in getPackageName.", e);
+                Log.d(TAG, "Dead object in getPackageName", e);
             }
         }
         return mPackageName;
@@ -452,7 +544,7 @@
             try {
                 mTag = mSessionBinder.getTag();
             } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in getTag.", e);
+                Log.d(TAG, "Dead object in getTag", e);
             }
         }
         return mTag;
@@ -652,7 +744,7 @@
             try {
                 mSessionBinder.prepare();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare.", e);
+                Log.wtf(TAG, "Error calling prepare", e);
             }
         }
 
@@ -671,12 +763,12 @@
         public void prepareFromMediaId(String mediaId, Bundle extras) {
             if (TextUtils.isEmpty(mediaId)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty String for prepareFromMediaId.");
+                        "You must specify a non-empty String for prepareFromMediaId");
             }
             try {
                 mSessionBinder.prepareFromMediaId(mediaId, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
+                Log.wtf(TAG, "Error calling prepare(" + mediaId + ")", e);
             }
         }
 
@@ -702,7 +794,7 @@
             try {
                 mSessionBinder.prepareFromSearch(query, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
+                Log.wtf(TAG, "Error calling prepare(" + query + ")", e);
             }
         }
 
@@ -721,12 +813,12 @@
         public void prepareFromUri(Uri uri, Bundle extras) {
             if (uri == null || Uri.EMPTY.equals(uri)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty Uri for prepareFromUri.");
+                        "You must specify a non-empty Uri for prepareFromUri");
             }
             try {
                 mSessionBinder.prepareFromUri(uri, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
+                Log.wtf(TAG, "Error calling prepare(" + uri + ")", e);
             }
         }
 
@@ -737,7 +829,7 @@
             try {
                 mSessionBinder.play();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play.", e);
+                Log.wtf(TAG, "Error calling play", e);
             }
         }
 
@@ -751,12 +843,12 @@
         public void playFromMediaId(String mediaId, Bundle extras) {
             if (TextUtils.isEmpty(mediaId)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty String for playFromMediaId.");
+                        "You must specify a non-empty String for playFromMediaId");
             }
             try {
                 mSessionBinder.playFromMediaId(mediaId, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
+                Log.wtf(TAG, "Error calling play(" + mediaId + ")", e);
             }
         }
 
@@ -778,7 +870,7 @@
             try {
                 mSessionBinder.playFromSearch(query, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + query + ").", e);
+                Log.wtf(TAG, "Error calling play(" + query + ")", e);
             }
         }
 
@@ -792,12 +884,12 @@
         public void playFromUri(Uri uri, Bundle extras) {
             if (uri == null || Uri.EMPTY.equals(uri)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty Uri for playFromUri.");
+                        "You must specify a non-empty Uri for playFromUri");
             }
             try {
                 mSessionBinder.playFromUri(uri, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + uri + ").", e);
+                Log.wtf(TAG, "Error calling play(" + uri + ")", e);
             }
         }
 
@@ -809,7 +901,7 @@
             try {
                 mSessionBinder.skipToQueueItem(id);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
+                Log.wtf(TAG, "Error calling skipToItem(" + id + ")", e);
             }
         }
 
@@ -821,7 +913,7 @@
             try {
                 mSessionBinder.pause();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling pause.", e);
+                Log.wtf(TAG, "Error calling pause", e);
             }
         }
 
@@ -833,7 +925,7 @@
             try {
                 mSessionBinder.stop();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling stop.", e);
+                Log.wtf(TAG, "Error calling stop", e);
             }
         }
 
@@ -846,7 +938,7 @@
             try {
                 mSessionBinder.seekTo(pos);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling seekTo.", e);
+                Log.wtf(TAG, "Error calling seekTo", e);
             }
         }
 
@@ -858,7 +950,7 @@
             try {
                 mSessionBinder.fastForward();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling fastForward.", e);
+                Log.wtf(TAG, "Error calling fastForward", e);
             }
         }
 
@@ -869,7 +961,7 @@
             try {
                 mSessionBinder.next();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling next.", e);
+                Log.wtf(TAG, "Error calling next", e);
             }
         }
 
@@ -881,7 +973,7 @@
             try {
                 mSessionBinder.rewind();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling rewind.", e);
+                Log.wtf(TAG, "Error calling rewind", e);
             }
         }
 
@@ -892,7 +984,7 @@
             try {
                 mSessionBinder.previous();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling previous.", e);
+                Log.wtf(TAG, "Error calling previous", e);
             }
         }
 
@@ -907,7 +999,7 @@
             try {
                 mSessionBinder.rate(rating);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling rate.", e);
+                Log.wtf(TAG, "Error calling rate", e);
             }
         }
 
@@ -923,7 +1015,7 @@
             try {
                 mSessionBinder.repeatMode(repeatMode);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling setRepeatMode.", e);
+                Log.wtf(TAG, "Error calling setRepeatMode", e);
             }
         }
 
@@ -936,7 +1028,7 @@
             try {
                 mSessionBinder.shuffleMode(enabled);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling shuffleMode.", e);
+                Log.wtf(TAG, "Error calling shuffleMode", e);
             }
         }
 
@@ -950,7 +1042,7 @@
         public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction,
                     @Nullable Bundle args) {
             if (customAction == null) {
-                throw new IllegalArgumentException("CustomAction cannot be null.");
+                throw new IllegalArgumentException("CustomAction cannot be null");
             }
             sendCustomAction(customAction.getAction(), args);
         }
@@ -966,12 +1058,12 @@
          */
         public void sendCustomAction(@NonNull String action, @Nullable Bundle args) {
             if (TextUtils.isEmpty(action)) {
-                throw new IllegalArgumentException("CustomAction cannot be null.");
+                throw new IllegalArgumentException("CustomAction cannot be null");
             }
             try {
                 mSessionBinder.sendCustomAction(action, args);
             } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in sendCustomAction.", e);
+                Log.d(TAG, "Dead object in sendCustomAction", e);
             }
         }
     }
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 84dc93a..bee3f52 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -87,6 +87,12 @@
     public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
 
     /**
+     * Set this flag on the session to indicate that it handles queue
+     * management commands through its {@link Callback}.
+     */
+    public static final int FLAG_HANDLES_QUEUE_COMMANDS = 1 << 2;
+
+    /**
      * System only flag for a session that needs to have priority over all other
      * sessions. This flag ensures this session will receive media button events
      * regardless of the current ordering in the system.
@@ -100,6 +106,7 @@
     @IntDef(flag = true, value = {
             FLAG_HANDLES_MEDIA_BUTTONS,
             FLAG_HANDLES_TRANSPORT_CONTROLS,
+            FLAG_HANDLES_QUEUE_COMMANDS,
             FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
     public @interface SessionFlags { }
 
@@ -645,6 +652,22 @@
         postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
     }
 
+    private void dispatchAddQueueItem(MediaDescription description) {
+        postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM, description);
+    }
+
+    private void dispatchAddQueueItem(MediaDescription description, int index) {
+        postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM_AT, description, index);
+    }
+
+    private void dispatchRemoveQueueItem(MediaDescription description) {
+        postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM, description);
+    }
+
+    private void dispatchRemoveQueueItemAt(int index) {
+        postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM_AT, index);
+    }
+
     private void dispatchMediaButton(Intent mediaButtonIntent) {
         postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent);
     }
@@ -666,10 +689,22 @@
         postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd);
     }
 
+    private void postToCallback(int what, int arg1) {
+        postToCallback(what, null, arg1);
+    }
+
     private void postToCallback(int what, Object obj) {
         postToCallback(what, obj, null);
     }
 
+    private void postToCallback(int what, Object obj, int arg1) {
+        synchronized (mLock) {
+            if (mCallback != null) {
+                mCallback.post(what, obj, arg1);
+            }
+        }
+    }
+
     private void postToCallback(int what, Object obj, Bundle extras) {
         synchronized (mLock) {
             if (mCallback != null) {
@@ -1043,6 +1078,47 @@
          */
         public void onCustomAction(@NonNull String action, @Nullable Bundle extras) {
         }
+
+        /**
+         * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given
+         * {@link MediaDescription description} at the end of the play queue.
+         *
+         * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be
+         *                    inserted.
+         */
+        public void onAddQueueItem(MediaDescription description) {
+        }
+
+        /**
+         * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given
+         * {@link MediaDescription description} at the specified position in the play queue.
+         *
+         * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be
+         *                    inserted.
+         * @param index The index at which the created {@link QueueItem} is to be inserted.
+         */
+        public void onAddQueueItem(MediaDescription description, int index) {
+        }
+
+        /**
+         * Called when a {@link MediaController} wants to remove the first occurrence of the
+         * specified {@link QueueItem} with the given {@link MediaDescription description}
+         * in the play queue.
+         *
+         * @param description The {@link MediaDescription} for denoting the {@link QueueItem} to be
+         *                    removed.
+         */
+        public void onRemoveQueueItem(MediaDescription description) {
+        }
+
+        /**
+         * Called when a {@link MediaController} wants to remove a {@link QueueItem} at the
+         * specified position in the play queue.
+         *
+         * @param index The index of the element to be removed.
+         */
+        public void onRemoveQueueItemAt(int index) {
+        }
     }
 
     /**
@@ -1239,6 +1315,38 @@
         }
 
         @Override
+        public void onAddQueueItem(MediaDescription description) {
+            MediaSession session = mMediaSession.get();
+            if (session != null) {
+                session.dispatchAddQueueItem(description);
+            }
+        }
+
+        @Override
+        public void onAddQueueItemAt(MediaDescription description, int index) {
+            MediaSession session = mMediaSession.get();
+            if (session != null) {
+                session.dispatchAddQueueItem(description, index);
+            }
+        }
+
+        @Override
+        public void onRemoveQueueItem(MediaDescription description) {
+            MediaSession session = mMediaSession.get();
+            if (session != null) {
+                session.dispatchRemoveQueueItem(description);
+            }
+        }
+
+        @Override
+        public void onRemoveQueueItemAt(int index) {
+            MediaSession session = mMediaSession.get();
+            if (session != null) {
+                session.dispatchRemoveQueueItemAt(index);
+            }
+        }
+
+        @Override
         public void onAdjustVolume(int direction) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
@@ -1376,6 +1484,10 @@
         private static final int MSG_CUSTOM_ACTION = 22;
         private static final int MSG_ADJUST_VOLUME = 23;
         private static final int MSG_SET_VOLUME = 24;
+        private static final int MSG_ADD_QUEUE_ITEM = 25;
+        private static final int MSG_ADD_QUEUE_ITEM_AT = 26;
+        private static final int MSG_REMOVE_QUEUE_ITEM = 27;
+        private static final int MSG_REMOVE_QUEUE_ITEM_AT = 28;
 
         private MediaSession.Callback mCallback;
 
@@ -1465,7 +1577,7 @@
                     mCallback.onSetRating((Rating) msg.obj);
                     break;
                 case MSG_REPEAT_MODE:
-                    mCallback.onSetRepeatMode((int) msg.obj);
+                    mCallback.onSetRepeatMode(msg.arg1);
                     break;
                 case MSG_SHUFFLE_MODE:
                     mCallback.onSetShuffleModeEnabled((boolean) msg.obj);
@@ -1473,12 +1585,24 @@
                 case MSG_CUSTOM_ACTION:
                     mCallback.onCustomAction((String) msg.obj, msg.getData());
                     break;
+                case MSG_ADD_QUEUE_ITEM:
+                    mCallback.onAddQueueItem((MediaDescription) msg.obj);
+                    break;
+                case MSG_ADD_QUEUE_ITEM_AT:
+                    mCallback.onAddQueueItem((MediaDescription) msg.obj, msg.arg1);
+                    break;
+                case MSG_REMOVE_QUEUE_ITEM:
+                    mCallback.onRemoveQueueItem((MediaDescription) msg.obj);
+                    break;
+                case MSG_REMOVE_QUEUE_ITEM_AT:
+                    mCallback.onRemoveQueueItemAt(msg.arg1);
+                    break;
                 case MSG_ADJUST_VOLUME:
                     synchronized (mLock) {
                         vp = mVolumeProvider;
                     }
                     if (vp != null) {
-                        vp.onAdjustVolume((int) msg.obj);
+                        vp.onAdjustVolume(msg.arg1);
                     }
                     break;
                 case MSG_SET_VOLUME:
@@ -1486,7 +1610,7 @@
                         vp = mVolumeProvider;
                     }
                     if (vp != null) {
-                        vp.onSetVolumeTo((int) msg.obj);
+                        vp.onSetVolumeTo(msg.arg1);
                     }
                     break;
             }
diff --git a/native/android/hardware_buffer.cpp b/native/android/hardware_buffer.cpp
index 2f75c10..e5e928d 100644
--- a/native/android/hardware_buffer.cpp
+++ b/native/android/hardware_buffer.cpp
@@ -26,10 +26,11 @@
 #include <android_runtime/android_hardware_HardwareBuffer.h>
 #include <binder/Binder.h>
 #include <binder/Parcel.h>
-#include <cutils/native_handle.h>
 #include <binder/IServiceManager.h>
+#include <cutils/native_handle.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/IGraphicBufferAlloc.h>
+#include <hardware/gralloc1.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/Flattenable.h>
 #include <utils/Log.h>
@@ -96,10 +97,14 @@
     }
 
     status_t err;
-    uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(
-            desc->usage0, desc->usage1);
+    uint64_t producerUsage = 0;
+    uint64_t consumerUsage = 0;
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(desc->usage0,
+            desc->usage1, &producerUsage, &consumerUsage);
     sp<GraphicBuffer> gbuffer = allocator->createGraphicBuffer(desc->width,
-            desc->height, format, desc->layers, usage, &err);
+            desc->height, format, desc->layers, producerUsage, consumerUsage,
+            std::string("AHardwareBuffer pid [") + std::to_string(getpid()) +
+            "]", &err);
     if (err != NO_ERROR) {
         return err;
     }
@@ -131,7 +136,7 @@
     outDesc->layers = gbuffer->getLayerCount();
     outDesc->usage0 =
             android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
-                    gbuffer->getUsage());
+                    gbuffer->getUsage(), gbuffer->getUsage());
     outDesc->usage1 = 0;
     outDesc->format = android_hardware_HardwareBuffer_convertFromPixelFormat(
             static_cast<uint32_t>(gbuffer->getPixelFormat()));
@@ -148,15 +153,19 @@
         return BAD_VALUE;
     }
 
-    uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(
-            usage0, 0);
+    uint64_t producerUsage = 0;
+    uint64_t consumerUsage = 0;
+    android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage0, 0,
+            &producerUsage, &consumerUsage);
     GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+    Rect bounds;
     if (!rect) {
-        return gBuffer->lockAsync(usage, outVirtualAddress, fence);
+        bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight()));
     } else {
-        Rect bounds(rect->left, rect->top, rect->right, rect->bottom);
-        return gBuffer->lockAsync(usage, bounds, outVirtualAddress, fence);
+        bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom));
     }
+    return gBuffer->lockAsync(producerUsage, consumerUsage, bounds,
+            outVirtualAddress, fence);
 }
 
 int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) {
diff --git a/opengl/java/android/opengl/GLU.java b/opengl/java/android/opengl/GLU.java
index ed64556..ef9bf167 100644
--- a/opengl/java/android/opengl/GLU.java
+++ b/opengl/java/android/opengl/GLU.java
@@ -203,8 +203,8 @@
      * @param view the current view, {x, y, width, height}
      * @param viewOffset the offset into the view array where the view vector
      *        data starts.
-     * @param obj the output vector {objX, objY, objZ}, that returns the
-     *        computed object coordinates.
+     * @param obj the output vector {objX, objY, objZ, objW}, that returns the
+     *        computed homogeneous object coordinates.
      * @param objOffset the offset into the obj array where the obj vector data
      *        starts.
      * @return A return value of GL10.GL_TRUE indicates success, a return value
diff --git a/packages/CompanionDeviceManager/Android.mk b/packages/CompanionDeviceManager/Android.mk
new file mode 100644
index 0000000..f730356
--- /dev/null
+++ b/packages/CompanionDeviceManager/Android.mk
@@ -0,0 +1,27 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CompanionDeviceManager
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
new file mode 100644
index 0000000..3eede54
--- /dev/null
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.companiondevicemanager">
+
+    <permission
+        android:name="com.android.companiondevicemanager.permission.BIND"
+        android:protectionLevel="signature" />
+
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+    <application
+        android:allowClearUserData="true"
+        android:label="@string/app_label"
+        android:allowBackup="false"
+        android:supportsRtl="true">
+
+        <service
+            android:name=".DeviceDiscoveryService"
+            android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
+            android:exported="true">
+        </service>
+
+        <activity
+            android:name=".DeviceChooserActivity"
+            android:theme="@*android:style/Theme.Dialog.NoFrame"
+            android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE">
+            <!--TODO include url scheme filter similar to PrintSpooler -->
+            <intent-filter>
+                <action android:name="android.companiondevice.START_DISCOVERY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+</manifest>
diff --git a/packages/CompanionDeviceManager/MODULE_LICENSE_APACHE2 b/packages/CompanionDeviceManager/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/CompanionDeviceManager/MODULE_LICENSE_APACHE2
diff --git a/packages/CompanionDeviceManager/NOTICE b/packages/CompanionDeviceManager/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/CompanionDeviceManager/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/packages/CompanionDeviceManager/res/layout/device_chooser.xml b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
new file mode 100644
index 0000000..ee08582
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="0.1"
+    >
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textColor="@android:color/black"
+        style="@*android:style/TextAppearance.Widget.Toolbar.Title"
+    />
+
+    <ListView
+        android:id="@+id/device_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@+id/title"
+        android:layout_above="@+id/buttons"
+        style="@android:style/Widget.Material.Light.ListView"
+    />
+
+    <LinearLayout
+        android:id="@+id/buttons"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentEnd="true"
+        android:gravity="end"
+    >
+        <Button
+            android:id="@+id/button_cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Cancel"
+            style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+        />
+        <Button
+            android:id="@+id/button_pair"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Pair"
+            style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+        />
+    </LinearLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/dimens.xml b/packages/CompanionDeviceManager/res/values/dimens.xml
new file mode 100644
index 0000000..da7b0d1
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!--  Padding applied on most UI elements  -->
+    <dimen name="padding">12dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
new file mode 100644
index 0000000..c4195b50
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Title of the CompanionDeviceManager application. [CHAR LIMIT=50] -->
+    <string name="app_label">Companion Device Manager</string>
+
+    <!-- Title of the device selection dialog. -->
+    <string name="chooser_title">Pair with &lt;strong&gt;<xliff:g id="app_name" example="Android Wear">%1$s</xliff:g>&lt;/strong&gt; via Bluetooth?</string>
+
+</resources>
diff --git a/core/res/res/values-ldrtl/dimens.xml b/packages/CompanionDeviceManager/res/values/themes.xml
similarity index 62%
copy from core/res/res/values-ldrtl/dimens.xml
copy to packages/CompanionDeviceManager/res/values/themes.xml
index 807c042..465f8fc 100644
--- a/core/res/res/values-ldrtl/dimens.xml
+++ b/packages/CompanionDeviceManager/res/values/themes.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
@@ -15,6 +15,11 @@
 -->
 
 <resources>
-    <item type="dimen" format="integer" name="time_picker_column_start_material">1</item>
-    <item type="dimen" format="integer" name="time_picker_column_end_material">0</item>
+
+    <!--TODO-->
+    <!--<style name="Theme.ChooserActivity" parent="@*android:style/Theme.Dialog.NoFrame">-->
+        <!--&lt;!&ndash;<item name="android:windowBackground">@android:color/light_grey</item>&ndash;&gt;-->
+        <!--<item name="android:backgroundColor">@android:color/light_grey</item>-->
+    <!--</style>-->
+
 </resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
new file mode 100644
index 0000000..c95f940
--- /dev/null
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.companiondevicemanager;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothDevice;
+import android.companion.CompanionDeviceManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.text.Html;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class DeviceChooserActivity extends Activity {
+
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "DeviceChooserActivity";
+
+    private ListView mDeviceListView;
+    private View mPairButton;
+    private View mCancelButton;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
+
+        setContentView(R.layout.device_chooser);
+        setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
+        getWindow().getDecorView().getRootView().setBackgroundColor(Color.LTGRAY); //TODO theme
+
+        if (getService().mDevicesFound.isEmpty()) {
+            Log.e(LOG_TAG, "About to show UI, but no devices to show");
+        }
+
+        final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
+        mDeviceListView = (ListView) findViewById(R.id.device_list);
+        mDeviceListView.setAdapter(adapter);
+        mDeviceListView.addFooterView(getProgressBar(), null, false);
+
+        mPairButton = findViewById(R.id.button_pair);
+        mPairButton.setOnClickListener((view) ->
+                onPairTapped(getService().mSelectedDevice));
+        adapter.registerDataSetObserver(new DataSetObserver() {
+            @Override
+            public void onChanged() {
+                updatePairButtonEnabled();
+            }
+        });
+        updatePairButtonEnabled();
+        mCancelButton = findViewById(R.id.button_cancel);
+        mCancelButton.setOnClickListener((view) -> {
+            setResult(RESULT_CANCELED);
+            finish();
+        });
+    }
+
+    private CharSequence getCallingAppName() {
+        try {
+            final PackageManager packageManager = getPackageManager();
+            return packageManager.getApplicationLabel(
+                    packageManager.getApplicationInfo(getService().mCallingPackage, 0));
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void setTitle(CharSequence title) {
+        final TextView titleView = (TextView) findViewById(R.id.title);
+        final int padding = getPadding(getResources());
+        titleView.setPadding(padding, padding, padding, padding);
+        titleView.setText(title);
+    }
+
+    //TODO put in resources xmls
+    private ProgressBar getProgressBar() {
+        final ProgressBar progressBar = new ProgressBar(this);
+        progressBar.setForegroundGravity(Gravity.CENTER_HORIZONTAL);
+        final int padding = getPadding(getResources());
+        progressBar.setPadding(padding, padding, padding, padding);
+        return progressBar;
+    }
+
+    static int getPadding(Resources r) {
+        return r.getDimensionPixelSize(R.dimen.padding);
+        //TODO
+//        final float dp = r.getDisplayMetrics().density;
+//        return (int)(12 * dp);
+    }
+
+    private void updatePairButtonEnabled() {
+        mPairButton.setEnabled(getService().mSelectedDevice != null);
+    }
+
+    private DeviceDiscoveryService getService() {
+        return DeviceDiscoveryService.sInstance;
+    }
+
+    protected void onPairTapped(BluetoothDevice selectedDevice) {
+        setResult(RESULT_OK,
+                new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
+        finish();
+    }
+
+    private void toast(String msg) {
+        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
+    }
+}
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
new file mode 100644
index 0000000..a3eec0d
--- /dev/null
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2013 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.companiondevicemanager;
+
+import static android.companion.BluetoothDeviceFilterUtils.getDeviceDisplayName;
+import static android.companion.BluetoothLEDeviceFilter.nullsafe;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+import android.companion.AssociationRequest;
+import android.companion.BluetoothDeviceFilterUtils;
+import android.companion.BluetoothLEDeviceFilter;
+import android.companion.ICompanionDeviceManagerService;
+import android.companion.IOnAssociateCallback;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class DeviceDiscoveryService extends Service {
+
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "DeviceDiscoveryService";
+
+    static DeviceDiscoveryService sInstance;
+
+    private BluetoothAdapter mBluetoothAdapter;
+    private BluetoothLEDeviceFilter mFilter;
+    private ScanFilter mScanFilter;
+    private ScanSettings mDefaultScanSettings = new ScanSettings.Builder().build();
+    List<BluetoothDevice> mDevicesFound;
+    BluetoothDevice mSelectedDevice;
+    DevicesAdapter mDevicesAdapter;
+    IOnAssociateCallback mCallback;
+    String mCallingPackage;
+
+    private final ICompanionDeviceManagerService mBinder =
+            new ICompanionDeviceManagerService.Stub() {
+        @Override
+        public void startDiscovery(AssociationRequest request,
+                IOnAssociateCallback callback,
+                String callingPackage) throws RemoteException {
+            if (DEBUG) {
+                Log.i(LOG_TAG,
+                        "startDiscovery() called with: filter = [" + request + "], callback = ["
+                                + callback + "]");
+            }
+            mCallback = callback;
+            mCallingPackage = callingPackage;
+            DeviceDiscoveryService.this.startDiscovery(request);
+        }
+    };
+
+    private final ScanCallback mBLEScanCallback = new ScanCallback() {
+        @Override
+        public void onScanResult(int callbackType, ScanResult result) {
+            final BluetoothDevice device = result.getDevice();
+            if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) {
+                onDeviceLost(device);
+            } else {
+                onDeviceFound(device);
+            }
+        }
+    };
+
+    private BluetoothLeScanner mBLEScanner;
+
+    private BroadcastReceiver mBluetoothDeviceFoundBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final BluetoothDevice device = intent.getParcelableExtra(
+                    BluetoothDevice.EXTRA_DEVICE);
+            if (!mFilter.matches(device)) return; // ignore device
+
+            if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
+                onDeviceFound(device);
+            } else {
+                onDeviceLost(device);
+            }
+        }
+    };
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (DEBUG) Log.i(LOG_TAG, "onBind(" + intent + ")");
+        return mBinder.asBinder();
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        if (DEBUG) Log.i(LOG_TAG, "onCreate()");
+
+        mBluetoothAdapter = getSystemService(BluetoothManager.class).getAdapter();
+        mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
+
+        mDevicesFound = new ArrayList<>();
+        mDevicesAdapter = new DevicesAdapter();
+
+        sInstance = this;
+    }
+
+    private void startDiscovery(AssociationRequest<?> request) {
+        //TODO support other protocols as well
+        mFilter = nullsafe((BluetoothLEDeviceFilter) request.getDeviceFilter());
+        mScanFilter = mFilter.getScanFilter();
+
+        reset();
+
+        final IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
+        intentFilter.addAction(BluetoothDevice.ACTION_DISAPPEARED);
+
+        registerReceiver(mBluetoothDeviceFoundBroadcastReceiver, intentFilter);
+        mBluetoothAdapter.startDiscovery();
+
+        mBLEScanner.startScan(
+                Collections.singletonList(mScanFilter), mDefaultScanSettings, mBLEScanCallback);
+    }
+
+    private void reset() {
+        mDevicesFound.clear();
+        mSelectedDevice = null;
+        mDevicesAdapter.notifyDataSetChanged();
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        stopScan();
+        return super.onUnbind(intent);
+    }
+
+    private void stopScan() {
+        if (DEBUG) Log.i(LOG_TAG, "stopScan() called");
+        mBluetoothAdapter.cancelDiscovery();
+        mBLEScanner.stopScan(mBLEScanCallback);
+        unregisterReceiver(mBluetoothDeviceFoundBroadcastReceiver);
+        stopSelf();
+    }
+
+    private void onDeviceFound(BluetoothDevice device) {
+        if (mDevicesFound.contains(device)) {
+            return;
+        }
+
+        if (DEBUG) {
+            Log.i(LOG_TAG, "Considering device " + getDeviceDisplayName(device));
+        }
+
+        if (!mFilter.matches(device)) {
+            return;
+        }
+
+        if (DEBUG) {
+            Log.i(LOG_TAG, "Found device " + getDeviceDisplayName(device));
+        }
+        if (mDevicesFound.isEmpty()) {
+            onReadyToShowUI();
+        }
+        mDevicesFound.add(device);
+        mDevicesAdapter.notifyDataSetChanged();
+    }
+
+    //TODO also, on timeout -> call onFailure
+    private void onReadyToShowUI() {
+        try {
+            mCallback.onSuccess(PendingIntent.getActivity(
+                    this, 0,
+                    new Intent(this, DeviceChooserActivity.class),
+                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
+                            | PendingIntent.FLAG_IMMUTABLE));
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void onDeviceLost(BluetoothDevice device) {
+        mDevicesFound.remove(device);
+        mDevicesAdapter.notifyDataSetChanged();
+        if (DEBUG) {
+            Log.i(LOG_TAG, "Lost device " + getDeviceDisplayName(device));
+        }
+    }
+
+    class DevicesAdapter extends ArrayAdapter<BluetoothDevice> {
+        private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
+
+        private Drawable icon(int drawableRes) {
+            Drawable icon = getResources().getDrawable(drawableRes, null);
+            icon.setTint(Color.DKGRAY);
+            return icon;
+        }
+
+        public DevicesAdapter() {
+            super(DeviceDiscoveryService.this, 0, mDevicesFound);
+        }
+
+        @Override
+        public View getView(
+                int position,
+                @Nullable View convertView,
+                @NonNull ViewGroup parent) {
+            TextView view = convertView instanceof TextView
+                    ? (TextView) convertView
+                    : newView();
+            bind(view, getItem(position));
+            return view;
+        }
+
+        private void bind(TextView textView, BluetoothDevice device) {
+            textView.setText(getDeviceDisplayName(device));
+            textView.setBackgroundColor(
+                    device.equals(mSelectedDevice)
+                            ? Color.GRAY
+                            : Color.TRANSPARENT);
+            textView.setOnClickListener((view) -> {
+                mSelectedDevice = device;
+                notifyDataSetChanged();
+            });
+        }
+
+        //TODO move to a layout file
+        private TextView newView() {
+            final TextView textView = new TextView(DeviceDiscoveryService.this);
+            textView.setTextColor(Color.BLACK);
+            final int padding = DeviceChooserActivity.getPadding(getResources());
+            textView.setPadding(padding, padding, padding, padding);
+            textView.setCompoundDrawablesWithIntrinsicBounds(
+                    BLUETOOTH_ICON, null, null, null);
+            textView.setCompoundDrawablePadding(padding);
+            return textView;
+        }
+    }
+}
diff --git a/packages/Keyguard/res/values-bn/strings.xml b/packages/Keyguard/res/values-bn/strings.xml
index 1a2a8dd..64c01bb 100644
--- a/packages/Keyguard/res/values-bn/strings.xml
+++ b/packages/Keyguard/res/values-bn/strings.xml
@@ -47,8 +47,8 @@
     <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"সিম কার্ডটি PUK কোড দিয়ে লক করা আছে৷"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"সিম কার্ড আনলক করা হচ্ছে…"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"পিন অঞ্চল"</string>
-    <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM পিন অঞ্চল"</string>
-    <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK অঞ্চল"</string>
+    <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"সিম পিন অঞ্চল"</string>
+    <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"সিম PUK অঞ্চল"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="7269583073750518672">"<xliff:g id="ALARM">%1$s</xliff:g> এ পরবর্তী অ্যালার্ম সেট করা হয়েছে"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"মুছুন"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
@@ -59,11 +59,11 @@
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"আপনার প্যাটার্ন আঁকুন"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"সিম পিন লিখুন"</string>
-    <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" এর জন্য SIM পিন লিখুন"</string>
+    <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" এর জন্য সিম পিন লিখুন"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"পিন লিখুন"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"পাসওয়ার্ড লিখুন"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"সিম এখন অক্ষম করা হয়েছে৷ অবিরত থাকতে PUK কোডটি লিখুন৷ বিশদ বিবরণের জন্য ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="363822494559783025">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" এখন অক্ষম করা হয়েছে৷ চালিয়ে যেতে PUK কোড লিখুন৷ বিস্তারিত জানার জন্য ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="363822494559783025">"সিম \"<xliff:g id="CARRIER">%1$s</xliff:g>\" এখন অক্ষম করা হয়েছে৷ চালিয়ে যেতে PUK কোড লিখুন৷ বিস্তারিত জানার জন্য ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"কাঙ্ক্ষিত পিন কোড লিখুন"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"কাঙ্ক্ষিত পিন কোড নিশ্চিত করুন"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"সিম কার্ড আনলক করা হচ্ছে…"</string>
@@ -91,13 +91,13 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ফোন আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ভুল সিম পিন কোড, আপনার ডিভাইসটি আনলক করতে এখন আপনাকে অবশ্যই আপনার ক্যারিয়ারের সাথে যোগাযোগ করতে হবে৷"</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
-      <item quantity="one">ভুল SIM পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
-      <item quantity="other">ভুল SIM পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
+      <item quantity="one">ভুল সিম পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
+      <item quantity="other">ভুল সিম পিন কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIMটি ব্যবহারের অযোগ্য৷ আপনার ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
-      <item quantity="one">ভুল SIM PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
-      <item quantity="other">ভুল SIM PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
+      <item quantity="one">ভুল সিম PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
+      <item quantity="other">ভুল সিম PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="6268288093558031564">"সিম পিন ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
     <string name="kg_password_puk_failed" msgid="2838824369502455984">"সিম PUK ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index b98a253..0fb7416 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -58,7 +58,7 @@
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Forkert pinkode"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Prøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Tegn dit mønster"</string>
-    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM"</string>
+    <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Indtast pinkode til SIM-kort"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"Indtast SIM-pinkoden for \"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Indtast pinkode"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"Angiv adgangskode"</string>
@@ -105,13 +105,13 @@
     <string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen dækning."</string>
     <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Skift indtastningsmetode"</string>
     <string name="airplane_mode" msgid="3122107900897202805">"Flytilstand"</string>
-    <string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du skal indtaste et mønster efter genstart af enheden"</string>
+    <string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du skal angive et mønster efter genstart af enheden"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Der skal indtaste en pinkode efter genstart af enheden"</string>
     <string name="kg_prompt_reason_restart_password" msgid="6504585392626524695">"Du skal indtaste en adgangskode efter genstart af enheden"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="3717506169674397620">"Der kræves et mønster som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="6951483704195396341">"Der kræves en pinkode som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="7306667546971345027">"Der kræves en adgangskode som ekstra beskyttelse"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="8476293962695171574">"Du skal indtaste et mønster, når du skifter profil"</string>
+    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="8476293962695171574">"Du skal angive et mønster, når du skifter profil"</string>
     <string name="kg_prompt_reason_switch_profiles_pin" msgid="2343607138520460043">"Du skal indtaste en pinkode, når du skifter profil"</string>
     <string name="kg_prompt_reason_switch_profiles_password" msgid="1295960907951965927">"Du skal indtaste en adgangskode, når du skifter profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="5838877342219587193">"Enhedsadministratoren har låst enheden"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
index 13bbc33..4b0ab59 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
@@ -94,16 +94,27 @@
 
     private static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
 
+    // Default dismiss control for smart suggestions.
+    private static final String DEFAULT_SMART_DISMISS_CONTROL = "0,10";
+
     private final Context mContext;
     private final List<SuggestionCategory> mSuggestionList;
     private final ArrayMap<Pair<String, String>, Tile> mAddCache = new ArrayMap<>();
     private final SharedPreferences mSharedPrefs;
+    private final String mSmartDismissControl;
 
-    public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) {
+
+    public SuggestionParser(
+        Context context, SharedPreferences sharedPrefs, int orderXml, String smartDismissControl) {
         mContext = context;
         mSuggestionList = (List<SuggestionCategory>) new SuggestionOrderInflater(mContext)
                 .parse(orderXml);
         mSharedPrefs = sharedPrefs;
+        mSmartDismissControl = smartDismissControl;
+    }
+
+    public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) {
+       this(context, sharedPrefs, orderXml, DEFAULT_SMART_DISMISS_CONTROL);
     }
 
     @VisibleForTesting
@@ -111,26 +122,35 @@
         mContext = context;
         mSuggestionList = new ArrayList<SuggestionCategory>();
         mSharedPrefs = sharedPrefs;
+        mSmartDismissControl = DEFAULT_SMART_DISMISS_CONTROL;
         Log.wtf(TAG, "Only use this constructor for testing");
     }
 
     public List<Tile> getSuggestions() {
+        return getSuggestions(false);
+    }
+
+    public List<Tile> getSuggestions(boolean isSmartSuggestionEnabled) {
         List<Tile> suggestions = new ArrayList<>();
         final int N = mSuggestionList.size();
         for (int i = 0; i < N; i++) {
-            readSuggestions(mSuggestionList.get(i), suggestions);
+            readSuggestions(mSuggestionList.get(i), suggestions, isSmartSuggestionEnabled);
         }
         return suggestions;
     }
 
+    public boolean dismissSuggestion(Tile suggestion) {
+        return dismissSuggestion(suggestion, false);
+    }
+
     /**
      * Dismisses a suggestion, returns true if the suggestion has no more dismisses left and should
      * be disabled.
      */
-    public boolean dismissSuggestion(Tile suggestion) {
+    public boolean dismissSuggestion(Tile suggestion, boolean isSmartSuggestionEnabled) {
         String keyBase = suggestion.intent.getComponent().flattenToShortString();
         int index = mSharedPrefs.getInt(keyBase + DISMISS_INDEX, 0);
-        String dismissControl = suggestion.metaData.getString(META_DATA_DISMISS_CONTROL);
+        String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
         if (dismissControl == null || parseDismissString(dismissControl).length == index) {
             return true;
         }
@@ -141,20 +161,23 @@
     }
 
     @VisibleForTesting
-    public void filterSuggestions(List<Tile> suggestions, int countBefore) {
+    public void filterSuggestions(
+        List<Tile> suggestions, int countBefore, boolean isSmartSuggestionEnabled) {
         for (int i = countBefore; i < suggestions.size(); i++) {
             if (!isAvailable(suggestions.get(i)) ||
                     !isSupported(suggestions.get(i)) ||
                     !satisifesRequiredUserType(suggestions.get(i)) ||
                     !satisfiesRequiredAccount(suggestions.get(i)) ||
                     !satisfiesConnectivity(suggestions.get(i)) ||
-                    isDismissed(suggestions.get(i))) {
+                    isDismissed(suggestions.get(i), isSmartSuggestionEnabled)) {
                 suggestions.remove(i--);
             }
         }
     }
 
-    private void readSuggestions(SuggestionCategory category, List<Tile> suggestions) {
+    @VisibleForTesting
+    void readSuggestions(
+        SuggestionCategory category, List<Tile> suggestions, boolean isSmartSuggestionEnabled) {
         int countBefore = suggestions.size();
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(category.category);
@@ -163,7 +186,7 @@
         }
         TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
                 mAddCache, null, suggestions, true, false);
-        filterSuggestions(suggestions, countBefore);
+        filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
         if (!category.multiple && suggestions.size() > (countBefore + 1)) {
             // If there are too many, remove them all and only re-add the one with the highest
             // priority.
@@ -288,12 +311,11 @@
         Settings.Secure.putInt(mContext.getContentResolver(), name, 1);
     }
 
-    private boolean isDismissed(Tile suggestion) {
-        Object dismissObj = suggestion.metaData.get(META_DATA_DISMISS_CONTROL);
-        if (dismissObj == null) {
+    private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
+        String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
+        if (dismissControl == null) {
             return false;
         }
-        String dismissControl = String.valueOf(dismissObj);
         String keyBase = suggestion.intent.getComponent().flattenToShortString();
         if (!mSharedPrefs.contains(keyBase + SETUP_TIME)) {
             mSharedPrefs.edit()
@@ -333,7 +355,16 @@
         return dismisses;
     }
 
-    private static class SuggestionCategory {
+    private String getDismissControl(Tile suggestion, boolean isSmartSuggestionEnabled) {
+        if (isSmartSuggestionEnabled) {
+            return mSmartDismissControl;
+        } else {
+            return suggestion.metaData.getString(META_DATA_DISMISS_CONTROL);
+        }
+    }
+
+    @VisibleForTesting
+    static class SuggestionCategory {
         public String category;
         public String pkg;
         public boolean multiple;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index 7e3f67b..d6bde81 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -36,7 +36,6 @@
     public static final String CATEGORY_SECURITY = "com.android.settings.category.ia.security";
     public static final String CATEGORY_ACCOUNT = "com.android.settings.category.ia.accounts";
     public static final String CATEGORY_SYSTEM = "com.android.settings.category.ia.system";
-    public static final String CATEGORY_SYSTEM_INPUT = "com.android.settings.category.ia.input";
     public static final String CATEGORY_SYSTEM_LANGUAGE =
             "com.android.settings.category.ia.language";
     public static final String CATEGORY_SYSTEM_DEVELOPMENT =
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 06ea445..82e69d8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -222,21 +222,21 @@
         if (isActive() && !other.isActive()) return -1;
         if (!isActive() && other.isActive()) return 1;
 
-        // Higher scores go before lower scores
-        if (mRankingScore != other.mRankingScore) {
-            return (mRankingScore > other.mRankingScore) ? -1 : 1;
-        }
-
         // Reachable one goes before unreachable one.
         if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
         if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
 
-        // Configured one goes before unconfigured one.
+        // Configured (saved) one goes before unconfigured one.
         if (networkId != WifiConfiguration.INVALID_NETWORK_ID
                 && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
         if (networkId == WifiConfiguration.INVALID_NETWORK_ID
                 && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
 
+        // Higher scores go before lower scores
+        if (mRankingScore != other.mRankingScore) {
+            return (mRankingScore > other.mRankingScore) ? -1 : 1;
+        }
+
         // Sort by signal strength, bucketed by level
         int difference = WifiManager.calculateSignalLevel(other.mRssi, SIGNAL_LEVELS)
                 - WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 7a89884a..596d614 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -43,6 +43,12 @@
 LOCAL_SRC_FILES := \
     $(call all-java-files-under, src)
 
+LOCAL_JAR_EXCLUDE_FILES := none
+
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/res
+
+
 include frameworks/base/packages/SettingsLib/common.mk
 
 include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml
new file mode 100644
index 0000000..1eeafba
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<optional-steps>
+    <step category="com.android.settings.suggested.category.LOCK_SCREEN" />
+    <step category="com.android.settings.suggested.category.EMAIL" />
+    <step category="com.android.settings.suggested.category.PARTNER_ACCOUNT"
+        multiple="true" />
+    <step category="com.android.settings.suggested.category.HOTWORD" />
+    <step category="com.android.settings.suggested.category.DEFAULT"
+        multiple="true" />
+    <step category="com.android.settings.suggested.category.SETTINGS_ONLY"
+        multiple="true" />
+</optional-steps>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
new file mode 100644
index 0000000..11c925e
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingLibRobolectricTestRunner.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.manifest.AndroidManifest;
+import org.robolectric.res.Fs;
+import org.robolectric.res.ResourcePath;
+
+import java.util.List;
+
+public class SettingLibRobolectricTestRunner extends RobolectricTestRunner {
+
+    public SettingLibRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+        super(testClass);
+    }
+
+    @Override
+    protected AndroidManifest getAppManifest(Config config) {
+        // Using the manifest file's relative path, we can figure out the application directory.
+        final String appRoot = "frameworks/base/packages/SettingsLib";
+        final String manifestPath = appRoot + "/AndroidManifest.xml";
+        final String resDir = appRoot + "/tests/robotests/res";
+        final String assetsDir = appRoot + config.assetDir();
+
+        final AndroidManifest manifest = new AndroidManifest(Fs.fileFromPath(manifestPath),
+                Fs.fileFromPath(resDir), Fs.fileFromPath(assetsDir));
+
+        manifest.setPackageName("com.android.settingslib");
+        return manifest;
+    }
+
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
new file mode 100644
index 0000000..0032cf0
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SuggestionParserTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+import android.util.Log;
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.preference.PreferenceManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import com.android.settingslib.drawer.Tile;
+import com.android.settingslib.drawer.TileUtilsTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SuggestionParserTest {
+
+    @Mock
+    private PackageManager mPackageManager;
+    private Context mContext;
+    private SuggestionParser mSuggestionParser;
+    private SuggestionParser.SuggestionCategory mSuggestioCategory;
+    private List<Tile> mSuggestionsBeforeDismiss;
+    private List<Tile> mSuggestionsAfterDismiss;
+    private SharedPreferences mPrefs;
+    private Tile mSuggestion;
+    private List<ResolveInfo> mInfo;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+        mSuggestion = new Tile();
+        mSuggestion.intent = new Intent("action");
+        mSuggestion.intent.setComponent(new ComponentName("pkg", "cls"));
+        mSuggestion.metaData = new Bundle();
+        mSuggestionParser = new SuggestionParser(
+            mContext, mPrefs, R.xml.suggestion_ordering, "0,0");
+        mSuggestioCategory = new SuggestionParser.SuggestionCategory();
+        mSuggestioCategory.category = "category1";
+        mSuggestioCategory.multiple = true;
+        mInfo = new ArrayList<>();
+        ResolveInfo info1 = TileUtilsTest.newInfo(true, "category1");
+        info1.activityInfo.packageName = "pkg";
+        ResolveInfo info2 = TileUtilsTest.newInfo(true, "category1");
+        info2.activityInfo.packageName = "pkg2";
+        mInfo.add(info1);
+        mInfo.add(info2);
+        when(mPackageManager.queryIntentActivitiesAsUser(
+            any(Intent.class), anyInt(), anyInt())).thenReturn(mInfo);
+    }
+
+    @Test
+    public void testDismissSuggestion_withoutSmartSuggestion() {
+        assertThat(mSuggestionParser.dismissSuggestion(mSuggestion, false)).isTrue();
+    }
+
+    @Test
+    public void testDismissSuggestion_withSmartSuggestion() {
+        assertThat(mSuggestionParser.dismissSuggestion(mSuggestion, true)).isFalse();
+    }
+
+    @Test
+    public void testGetSuggestions_withoutSmartSuggestions() {
+        readAndDismissSuggestion(false);
+        mSuggestionParser.readSuggestions(mSuggestioCategory, mSuggestionsAfterDismiss, false);
+        assertThat(mSuggestionsBeforeDismiss.size()).isEqualTo(2);
+        assertThat(mSuggestionsAfterDismiss.size()).isEqualTo(1);
+        assertThat(mSuggestionsBeforeDismiss.get(1)).isEqualTo(mSuggestionsAfterDismiss.get(0));
+    }
+
+    @Test
+    public void testGetSuggestions_withSmartSuggestions() {
+        readAndDismissSuggestion(true);
+        assertThat(mSuggestionsBeforeDismiss.size()).isEqualTo(2);
+        assertThat(mSuggestionsAfterDismiss.size()).isEqualTo(2);
+        assertThat(mSuggestionsBeforeDismiss).isEqualTo(mSuggestionsAfterDismiss);
+    }
+
+    private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
+        mSuggestionsBeforeDismiss = new ArrayList<Tile>();
+        mSuggestionsAfterDismiss = new ArrayList<Tile>();
+        mSuggestionParser.readSuggestions(
+            mSuggestioCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled);
+        if (mSuggestionParser.dismissSuggestion(
+            mSuggestionsBeforeDismiss.get(0), isSmartSuggestionEnabled)) {
+            mInfo.remove(0);
+        }
+        mSuggestionParser.readSuggestions(
+            mSuggestioCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
index b209f4e..40353e7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -56,12 +56,11 @@
         allKeys.add(CategoryKey.CATEGORY_SECURITY);
         allKeys.add(CategoryKey.CATEGORY_ACCOUNT);
         allKeys.add(CategoryKey.CATEGORY_SYSTEM);
-        allKeys.add(CategoryKey.CATEGORY_SYSTEM_INPUT);
         allKeys.add(CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
         allKeys.add(CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
         // DO NOT REMOVE ANYTHING ABOVE
 
-        assertThat(allKeys.size()).isEqualTo(14);
+        assertThat(allKeys.size()).isEqualTo(13);
     }
 
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 021a96c..1683901 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -40,6 +40,7 @@
 
 import com.android.settingslib.SuggestionParser;
 import com.android.settingslib.TestConfig;
+import com.android.settingslib.drawer.TileUtilsTest;
 import static org.mockito.Mockito.atLeastOnce;
 
 import org.junit.Before;
@@ -179,7 +180,7 @@
 
         assertThat(outTiles.size()).isEqualTo(1);
         SuggestionParser parser = new SuggestionParser(mContext, null);
-        parser.filterSuggestions(outTiles, 0);
+        parser.filterSuggestions(outTiles, 0, false);
         assertThat(outTiles.size()).isEqualTo(0);
     }
 
@@ -303,16 +304,16 @@
         assertThat(outTiles.get(0).summary).isEqualTo("dynamic-summary");
     }
 
-    private ResolveInfo newInfo(boolean systemApp, String category) {
+    public static ResolveInfo newInfo(boolean systemApp, String category) {
         return newInfo(systemApp, category, null);
     }
 
-    private ResolveInfo newInfo(boolean systemApp, String category, String keyHint) {
+    private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint) {
         return newInfo(systemApp, category, keyHint, null, null);
     }
 
-    private ResolveInfo newInfo(boolean systemApp, String category, String keyHint, String iconUri,
-            String summaryUri) {
+    private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint,
+        String iconUri, String summaryUri) {
         ResolveInfo info = new ResolveInfo();
         info.system = systemApp;
         info.activityInfo = new ActivityInfo();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 8bbc8c9..4ddafac 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1399,9 +1399,6 @@
                 Settings.Secure.NIGHT_DISPLAY_CUSTOM_END_TIME,
                 SecureSettingsProto.NIGHT_DISPLAY_CUSTOM_END_TIME);
         dumpSetting(s, p,
-                Settings.Secure.BRIGHTNESS_USE_TWILIGHT,
-                SecureSettingsProto.BRIGHTNESS_USE_TWILIGHT);
-        dumpSetting(s, p,
                 Settings.Secure.ENABLED_VR_LISTENERS,
                 SecureSettingsProto.ENABLED_VR_LISTENERS);
         dumpSetting(s, p,
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 6d76798..8cc2ce2 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -38,5 +38,5 @@
 -keep class ** extends android.support.v14.preference.PreferenceFragment
 -keep class com.android.systemui.tuner.*
 -keep class com.android.systemui.plugins.** {
-    public protected **;
+    public protected *;
 }
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..0615668
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..839e5ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..1480c865
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..66e11fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..d2fe0c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..5923269
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..d0196e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..d3a2b39
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button.png
new file mode 100644
index 0000000..726643c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button_dark.png
new file mode 100644
index 0000000..31078f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_accessibility_button_dark.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
index ea03a50..4987f9b 100644
--- a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
+++ b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
@@ -15,5 +15,5 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
   <solid android:color="#61FFFFFF" />
-  <corners android:radius="@dimen/recents_grid_task_view_rounded_corners_radius"/>
+  <corners android:radius="@dimen/recents_grid_task_view_focused_frame_rounded_corners_radius"/>
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 5e85ba0..6bd79a4 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -39,4 +39,13 @@
         android:contentDescription="@string/accessibility_ime_switch_button"
         android:scaleType="centerInside"
         />
+    <com.android.systemui.statusbar.policy.KeyButtonView
+        android:id="@+id/accessibility_button"
+        android:layout_width="@dimen/navigation_extra_key_width"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="2dp"
+        android:visibility="invisible"
+        android:contentDescription="@string/accessibility_accessibility_button"
+        android:scaleType="centerInside"
+    />
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 92a9da9..c2686f8 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -73,7 +73,7 @@
     <include layout="@layout/status_bar_expanded"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:visibility="gone" />
+        android:visibility="invisible" />
 
     <com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_in_front"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/dimens_grid.xml b/packages/SystemUI/res/values/dimens_grid.xml
index 5858443..febf65b8 100644
--- a/packages/SystemUI/res/values/dimens_grid.xml
+++ b/packages/SystemUI/res/values/dimens_grid.xml
@@ -22,6 +22,7 @@
   <dimen name="recents_grid_task_view_header_height">44dp</dimen>
   <dimen name="recents_grid_task_view_header_button_padding">8dp</dimen>
   <dimen name="recents_grid_task_view_focused_frame_thickness">8dp</dimen>
-  <dimen name="recents_grid_task_view_rounded_corners_radius">8dp</dimen>
+  <dimen name="recents_grid_task_view_rounded_corners_radius">4dp</dimen>
+  <dimen name="recents_grid_task_view_focused_frame_rounded_corners_radius">8dp</dimen>
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 363b3e2..8553952 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -207,6 +207,8 @@
     <string name="accessibility_home">Home</string>
     <!-- Content description of the menu button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_menu">Menu</string>
+    <!-- Content description of the accessibility button in the navigation bar (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_accessibility_button">Accessibility</string>
     <!-- Content description of the recents button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_recent">Overview</string>
     <!-- Content description of the search button for accessibility. [CHAR LIMIT=NONE] -->
@@ -1761,14 +1763,6 @@
         not appear on production builds ever. -->
     <string name="pip_drag_to_dismiss_summary" translatable="false">Drag to the dismiss target at the bottom of the screen to close the PIP</string>
 
-    <!-- PIP allow minimize title. Non-translatable since it should
-        not appear on production builds ever. -->
-    <string name="pip_allow_minimize_title" translatable="false">Allow PIP to minimize</string>
-
-    <!-- PIP allow minimize description. Non-translatable since it should
-        not appear on production builds ever. -->
-    <string name="pip_allow_minimize_summary" translatable="false">Allow PIP to minimize slightly offscreen</string>
-
     <!-- Tuner string -->
     <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
     <!-- Tuner string -->
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 94a7c07..6198ab7 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -131,12 +131,6 @@
           android:summary="@string/pip_drag_to_dismiss_summary"
           sysui:defValue="false" />
 
-        <com.android.systemui.tuner.TunerSwitch
-            android:key="pip_allow_minimize"
-            android:title="@string/pip_allow_minimize_title"
-            android:summary="@string/pip_allow_minimize_summary"
-            sysui:defValue="true" />
-
     </PreferenceScreen>
 
     <PreferenceScreen
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index a9ac2d9..27070ed 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -87,6 +87,7 @@
      * above.
      */
     private final Class<?>[] SERVICES_PER_USER = new Class[] {
+            Dependency.class,
             Recents.class,
             PipUI.class
     };
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index aa22618..7c15096 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.doze;
 
+import android.app.AlarmManager;
 import android.app.Application;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -25,10 +26,7 @@
 import android.os.SystemClock;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIApplication;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.doze.DozeProvider;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
@@ -45,6 +43,7 @@
         Context context = dozeService;
         SensorManager sensorManager = context.getSystemService(SensorManager.class);
         PowerManager powerManager = context.getSystemService(PowerManager.class);
+        AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
 
         DozeHost host = getHost(dozeService);
         AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
@@ -57,7 +56,7 @@
         machine.setParts(new DozeMachine.Part[]{
                 createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
                         machine),
-                createDozeUi(context, host, wakeLock, machine),
+                createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
         });
 
         return machine;
@@ -72,7 +71,7 @@
     }
 
     private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
-            DozeMachine machine) {
+            DozeMachine machine, Handler handler, AlarmManager alarmManager) {
         if (mDozePlugin != null) {
             DozeProvider.DozeUi dozeUi = mDozePlugin.provideDozeUi(context,
                     pluginMachine(context, machine, host),
@@ -82,7 +81,7 @@
                         pluginState(newState));
             };
         } else {
-            return new DozeUi(context, machine, wakeLock, host);
+            return new DozeUi(context, alarmManager, machine, wakeLock, host, handler);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 00d2298..f3fb1ef 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -30,15 +30,12 @@
     void stopDozing();
     void dozeTimeTick();
     boolean isPowerSaveActive();
-    boolean isNotificationLightOn();
     boolean isPulsingBlocked();
 
     void startPendingIntentDismissingKeyguard(PendingIntent intent);
 
     interface Callback {
-        default void onNewNotifications() {}
         default void onNotificationHeadsUp() {}
-        default void onNotificationLight(boolean on) {}
         default void onPowerSaveChanged(boolean active) {}
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 95e49ce..76e0283 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -16,7 +16,13 @@
 
 package com.android.systemui.doze;
 
+import android.app.AlarmManager;
 import android.content.Context;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 
 /**
  * The policy controlling doze.
@@ -24,16 +30,25 @@
 public class DozeUi implements DozeMachine.Part {
 
     private final Context mContext;
+    private final AlarmManager mAlarmManager;
     private final DozeHost mHost;
-    private DozeFactory.WakeLock mWakeLock;
-    private DozeMachine mMachine;
+    private final Handler mHandler;
+    private final DozeFactory.WakeLock mWakeLock;
+    private final DozeMachine mMachine;
+    private final AlarmManager.OnAlarmListener mTimeTick;
 
-    public DozeUi(Context context, DozeMachine machine, DozeFactory.WakeLock wakeLock,
-            DozeHost host) {
+    private boolean mTimeTickScheduled = false;
+
+    public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
+            DozeFactory.WakeLock wakeLock, DozeHost host, Handler handler) {
         mContext = context;
+        mAlarmManager = alarmManager;
         mMachine = machine;
         mWakeLock = wakeLock;
         mHost = host;
+        mHandler = handler;
+
+        mTimeTick = this::onTimeTick;
     }
 
     private void pulseWhileDozing(int reason) {
@@ -54,6 +69,12 @@
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         switch (newState) {
+            case DOZE_AOD:
+                scheduleTimeTick();
+                break;
+            case DOZE:
+                unscheduleTimeTick();
+                break;
             case DOZE_REQUEST_PULSE:
                 pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
                 break;
@@ -62,7 +83,52 @@
                 break;
             case FINISH:
                 mHost.stopDozing();
+                unscheduleTimeTick();
                 break;
         }
     }
+
+    private void scheduleTimeTick() {
+        if (mTimeTickScheduled) {
+            return;
+        }
+
+        long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
+        mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
+
+        mTimeTickScheduled = true;
+    }
+
+    private void unscheduleTimeTick() {
+        if (!mTimeTickScheduled) {
+            return;
+        }
+        mAlarmManager.cancel(mTimeTick);
+    }
+
+    private long roundToNextMinute(long timeInMillis) {
+        Calendar calendar = GregorianCalendar.getInstance();
+        calendar.setTimeInMillis(timeInMillis);
+        calendar.set(Calendar.MILLISECOND, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.add(Calendar.MINUTE, 1);
+
+        return calendar.getTimeInMillis();
+    }
+
+    private void onTimeTick() {
+        if (!mTimeTickScheduled) {
+            // Alarm was canceled, but we still got the callback. Ignore.
+            return;
+        }
+
+        mHost.dozeTimeTick();
+
+        // Keep wakelock until a frame has been pushed.
+        mHandler.post(mWakeLock.wrap(() -> {}));
+
+        mTimeTickScheduled = false;
+        scheduleTimeTick();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index e182176..beec137 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -17,18 +17,15 @@
 package com.android.systemui.pip.phone;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.TouchDelegate;
 import android.view.View;
 import android.view.View.OnLayoutChangeListener;
 import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
 import android.widget.FrameLayout;
 
 import com.android.systemui.Interpolators;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 3df557d..f59b2a4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,20 +16,16 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.app.ActivityManager;
-import android.app.ActivityManager.StackInfo;
-import android.app.ActivityOptions;
 import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ParceledListSlice;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.Log;
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
@@ -94,7 +90,7 @@
                 }
             }
             if (expandPipToFullscreen) {
-                mTouchHandler.expandPinnedStackToFullscreen();
+                mTouchHandler.getMotionHelper().expandPip();
             } else {
                 Log.w(TAG, "Can not expand PiP to fullscreen via intent from the same package.");
             }
@@ -114,28 +110,31 @@
         }
 
         @Override
-        public void onBoundsChanged(boolean adjustedForIme) {
-            // Do nothing
-        }
-
-        @Override
-        public void onActionsChanged(ParceledListSlice actions) {
+        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
             mHandler.post(() -> {
-                mMenuController.setAppActions(actions);
+                mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
             });
         }
 
         @Override
         public void onMinimizedStateChanged(boolean isMinimized) {
             mHandler.post(() -> {
-                mTouchHandler.onMinimizedStateChanged(isMinimized);
+                mTouchHandler.setMinimizedState(isMinimized, true /* fromController */);
             });
         }
 
         @Override
-        public void onSnapToEdgeStateChanged(boolean isSnapToEdge) {
+        public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+                boolean fromImeAdjustement) {
             mHandler.post(() -> {
-                mTouchHandler.onSnapToEdgeStateChanged(isSnapToEdge);
+                mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, fromImeAdjustement);
+            });
+        }
+
+        @Override
+        public void onActionsChanged(ParceledListSlice actions) {
+            mHandler.post(() -> {
+                mMenuController.setAppActions(actions);
             });
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index d96baa6..5a665a9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -16,16 +16,22 @@
 
 package com.android.systemui.pip.phone;
 
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+
 import android.app.IActivityManager;
+import android.app.PendingIntent;
 import android.app.RemoteAction;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.drawable.Icon;
 import android.media.session.MediaController;
-import android.media.session.MediaController.TransportControls;
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
+import android.os.UserHandle;
 
 import com.android.systemui.R;
 
@@ -40,6 +46,9 @@
  */
 public class PipMediaController {
 
+    private static final String ACTION_PLAY = "com.android.systemui.pip.phone.PLAY";
+    private static final String ACTION_PAUSE = "com.android.systemui.pip.phone.PAUSE";
+
     /**
      * A listener interface to receive notification on changes to the media actions.
      */
@@ -59,6 +68,18 @@
     private RemoteAction mPauseAction;
     private RemoteAction mPlayAction;
 
+    private BroadcastReceiver mPlayPauseActionReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (action.equals(ACTION_PLAY)) {
+                mMediaController.getTransportControls().play();
+            } else if (action.equals(ACTION_PAUSE)) {
+                mMediaController.getTransportControls().pause();
+            }
+        }
+    };
+
     private MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() {
         @Override
         public void onPlaybackStateChanged(PlaybackState state) {
@@ -73,6 +94,10 @@
     public PipMediaController(Context context, IActivityManager activityManager) {
         mContext = context;
         mActivityManager = activityManager;
+        IntentFilter mediaControlFilter = new IntentFilter();
+        mediaControlFilter.addAction(ACTION_PLAY);
+        mediaControlFilter.addAction(ACTION_PAUSE);
+        mContext.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter);
 
         createMediaActions();
         mMediaSessionManager =
@@ -135,12 +160,14 @@
         String pauseDescription = mContext.getString(R.string.pip_pause);
         mPauseAction = new RemoteAction(Icon.createWithResource(mContext,
                 R.drawable.ic_pause_white_24dp), pauseDescription, pauseDescription,
-                action -> mMediaController.getTransportControls().pause());
+                        PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PAUSE),
+                                FLAG_UPDATE_CURRENT));
 
         String playDescription = mContext.getString(R.string.pip_play);
         mPlayAction = new RemoteAction(Icon.createWithResource(mContext,
                 R.drawable.ic_play_arrow_white_24dp), playDescription, playDescription,
-                action -> mMediaController.getTransportControls().play());
+                        PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PLAY),
+                                FLAG_UPDATE_CURRENT));
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 438b8dd..9066977 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.PendingIntent.CanceledException;
 import android.app.RemoteAction;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
@@ -258,7 +259,11 @@
                     }, mHandler);
                     actionView.setContentDescription(action.getContentDescription());
                     actionView.setOnClickListener(v -> {
-                        action.sendActionInvoked();
+                        try {
+                            action.getActionIntent().send();
+                        } catch (CanceledException e) {
+                            Log.w(TAG, "Failed to send action", e);
+                        }
                     });
                     actionsGroup.addView(actionView);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
new file mode 100644
index 0000000..28ab3fb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -0,0 +1,376 @@
+/*
+ * 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.systemui.pip.phone;
+
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+
+import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
+import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.RectEvaluator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.ActivityManager.StackInfo;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.animation.Interpolator;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.statusbar.FlingAnimationUtils;
+
+/**
+ * A helper to animate and manipulate the PiP.
+ */
+public class PipMotionHelper {
+
+    private static final String TAG = "PipMotionHelper";
+
+    private static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
+
+    private static final int DEFAULT_MOVE_STACK_DURATION = 225;
+    private static final int SNAP_STACK_DURATION = 225;
+    private static final int DISMISS_STACK_DURATION = 375;
+    private static final int SHRINK_STACK_FROM_MENU_DURATION = 175;
+    private static final int EXPAND_STACK_TO_MENU_DURATION = 175;
+    private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 225;
+    private static final int MINIMIZE_STACK_MAX_DURATION = 200;
+
+    // The fraction of the stack width that the user has to drag offscreen to minimize the PiP
+    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
+
+    private Context mContext;
+    private IActivityManager mActivityManager;
+    private Handler mHandler;
+
+    private PipSnapAlgorithm mSnapAlgorithm;
+    private FlingAnimationUtils mFlingAnimationUtils;
+
+    private final Rect mBounds = new Rect();
+    private final Rect mStableInsets = new Rect();
+
+    private ValueAnimator mBoundsAnimator = null;
+    private ValueAnimator.AnimatorUpdateListener mUpdateBoundsListener =
+            new AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    mBounds.set((Rect) animation.getAnimatedValue());
+                }
+            };
+
+    public PipMotionHelper(Context context, IActivityManager activityManager,
+            PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils) {
+        mContext = context;
+        mHandler = BackgroundThread.getHandler();
+        mActivityManager = activityManager;
+        mSnapAlgorithm = snapAlgorithm;
+        mFlingAnimationUtils = flingAnimationUtils;
+        onConfigurationChanged();
+    }
+
+    /**
+     * Updates whenever the configuration changes.
+     */
+    void onConfigurationChanged() {
+        mSnapAlgorithm.onConfigurationChanged();
+        SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+    }
+
+    /**
+     * Synchronizes the current bounds with the pinned stack.
+     */
+    void synchronizePinnedStackBounds() {
+        cancelAnimations();
+        try {
+            StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+            mBounds.set(stackInfo.bounds);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to get pinned stack bounds");
+        }
+    }
+
+    /**
+     * Tries to the move the pinned stack to the given {@param bounds}.
+     */
+    void movePip(Rect toBounds) {
+        cancelAnimations();
+        resizePipUnchecked(toBounds);
+        mBounds.set(toBounds);
+    }
+
+    /**
+     * Resizes the pinned stack back to fullscreen.
+     */
+    void expandPip() {
+        cancelAnimations();
+        mHandler.post(() -> {
+            try {
+                mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
+                        true /* allowResizeInDockedMode */, true /* preserveWindows */,
+                        true /* animate */, EXPAND_STACK_TO_FULLSCREEN_DURATION);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error showing PiP menu activity", e);
+            }
+        });
+    }
+
+    /**
+     * Dismisses the pinned stack.
+     */
+    void dismissPip() {
+        cancelAnimations();
+        mHandler.post(() -> {
+            try {
+                mActivityManager.removeStack(PINNED_STACK_ID);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to remove PiP", e);
+            }
+        });
+    }
+
+    /**
+     * @return the PiP bounds.
+     */
+    Rect getBounds() {
+        return mBounds;
+    }
+
+    /**
+     * @return the closest minimized PiP bounds.
+     */
+    Rect getClosestMinimizedBounds(Rect stackBounds, Rect movementBounds) {
+        Point displaySize = new Point();
+        mContext.getDisplay().getRealSize(displaySize);
+        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, stackBounds);
+        mSnapAlgorithm.applyMinimizedOffset(toBounds, movementBounds, displaySize, mStableInsets);
+        return toBounds;
+    }
+
+    /**
+     * @return whether the PiP at the current bounds should be minimized.
+     */
+    boolean shouldMinimizePip() {
+        Point displaySize = new Point();
+        mContext.getDisplay().getRealSize(displaySize);
+        if (mBounds.left < 0) {
+            float offscreenFraction = (float) -mBounds.left / mBounds.width();
+            return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION;
+        } else if (mBounds.right > displaySize.x) {
+            float offscreenFraction = (float) (mBounds.right - displaySize.x) /
+                    mBounds.width();
+            return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Flings the minimized PiP to the closest minimized snap target.
+     */
+    Rect flingToMinimizedState(float velocityY, Rect movementBounds) {
+        cancelAnimations();
+        // We currently only allow flinging the minimized stack up and down, so just lock the
+        // movement bounds to the current stack bounds horizontally
+        movementBounds = new Rect(mBounds.left, movementBounds.top, mBounds.left,
+                movementBounds.bottom);
+        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds,
+                0 /* velocityX */, velocityY);
+        if (!mBounds.equals(toBounds)) {
+            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN,
+                    mUpdateBoundsListener);
+            mFlingAnimationUtils.apply(mBoundsAnimator, 0,
+                    distanceBetweenRectOffsets(mBounds, toBounds),
+                    velocityY);
+            mBoundsAnimator.start();
+        }
+        return toBounds;
+    }
+
+    /**
+     * Animates the PiP to the minimized state, slightly offscreen.
+     */
+    Rect animateToClosestMinimizedState(Rect movementBounds,
+            final PipMenuActivityController menuController) {
+        cancelAnimations();
+        Rect toBounds = getClosestMinimizedBounds(mBounds, movementBounds);
+        if (!mBounds.equals(toBounds)) {
+            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
+                    MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN, mUpdateBoundsListener);
+            mBoundsAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    menuController.hideMenu();
+                }
+            });
+            mBoundsAnimator.start();
+        }
+        return toBounds;
+    }
+
+    /**
+     * Flings the PiP to the closest snap target.
+     */
+    Rect flingToSnapTarget(float velocity, float velocityX, float velocityY, Rect movementBounds) {
+        cancelAnimations();
+        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds,
+                velocityX, velocityY);
+        if (!mBounds.equals(toBounds)) {
+            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, 0, FAST_OUT_SLOW_IN,
+                    mUpdateBoundsListener);
+            mFlingAnimationUtils.apply(mBoundsAnimator, 0,
+                    distanceBetweenRectOffsets(mBounds, toBounds),
+                    velocity);
+            mBoundsAnimator.start();
+        }
+        return toBounds;
+    }
+
+    /**
+     * Animates the PiP to the closest snap target.
+     */
+    Rect animateToClosestSnapTarget(Rect movementBounds) {
+        cancelAnimations();
+        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mBounds);
+        if (!mBounds.equals(toBounds)) {
+            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, SNAP_STACK_DURATION,
+                    FAST_OUT_SLOW_IN, mUpdateBoundsListener);
+            mBoundsAnimator.start();
+        }
+        return toBounds;
+    }
+
+    /**
+     * Animates the PiP to the expanded state to show the menu.
+     */
+    float animateToExpandedState(Rect expandedBounds, Rect movementBounds,
+            Rect expandedMovementBounds) {
+        float savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds), movementBounds);
+        mSnapAlgorithm.applySnapFraction(expandedBounds, expandedMovementBounds, savedSnapFraction);
+        mBoundsAnimator = createAnimationToBounds(mBounds, expandedBounds,
+                EXPAND_STACK_TO_MENU_DURATION, FAST_OUT_SLOW_IN, mUpdateBoundsListener);
+        mBoundsAnimator.start();
+        return savedSnapFraction;
+    }
+
+    /**
+     * Animates the PiP from the expanded state to the normal state after the menu is hidden.
+     */
+    void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction,
+            Rect normalMovementBounds) {
+        if (savedSnapFraction >= 0f) {
+            mSnapAlgorithm.applySnapFraction(normalBounds, normalMovementBounds, savedSnapFraction);
+            mBoundsAnimator = createAnimationToBounds(mBounds, normalBounds,
+                    SHRINK_STACK_FROM_MENU_DURATION, FAST_OUT_SLOW_IN, mUpdateBoundsListener);
+            mBoundsAnimator.start();
+        } else {
+            animateToClosestSnapTarget(normalMovementBounds);
+        }
+    }
+
+    /**
+     * Animates the dismissal of the PiP over the dismiss target bounds.
+     */
+    Rect animateDismissFromDrag(Rect dismissBounds) {
+        cancelAnimations();
+        Rect toBounds = new Rect(dismissBounds.centerX(),
+                dismissBounds.centerY(),
+                dismissBounds.centerX() + 1,
+                dismissBounds.centerY() + 1);
+        mBoundsAnimator = createAnimationToBounds(mBounds, toBounds, DISMISS_STACK_DURATION,
+                FAST_OUT_LINEAR_IN, mUpdateBoundsListener);
+        mBoundsAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                dismissPip();
+            }
+        });
+        mBoundsAnimator.start();
+        return toBounds;
+    }
+
+    /**
+     * Animates the PiP to some given bounds.
+     */
+    void animateToBounds(Rect toBounds) {
+        cancelAnimations();
+        if (!mBounds.equals(toBounds)) {
+            mBoundsAnimator = createAnimationToBounds(mBounds, toBounds,
+                    DEFAULT_MOVE_STACK_DURATION, FAST_OUT_LINEAR_IN, mUpdateBoundsListener);
+            mBoundsAnimator.start();
+        }
+    }
+
+    /**
+     * Cancels all existing animations.
+     */
+    void cancelAnimations() {
+        if (mBoundsAnimator != null) {
+            mBoundsAnimator.cancel();
+            mBoundsAnimator = null;
+        }
+    }
+
+    /**
+     * Creates an animation to move the PiP to give given {@param toBounds}.
+     */
+    private ValueAnimator createAnimationToBounds(Rect fromBounds, Rect toBounds, int duration,
+            Interpolator interpolator, ValueAnimator.AnimatorUpdateListener updateListener) {
+        ValueAnimator anim = ValueAnimator.ofObject(RECT_EVALUATOR, fromBounds, toBounds);
+        anim.setDuration(duration);
+        anim.setInterpolator(interpolator);
+        anim.addUpdateListener((ValueAnimator animation) -> {
+            resizePipUnchecked((Rect) animation.getAnimatedValue());
+        });
+        if (updateListener != null) {
+            anim.addUpdateListener(updateListener);
+        }
+        return anim;
+    }
+
+    /**
+     * Directly resizes the PiP to the given {@param bounds}.
+     */
+    private void resizePipUnchecked(Rect toBounds) {
+        if (!toBounds.equals(mBounds)) {
+            mHandler.post(() -> {
+                try {
+                    mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
+                    mBounds.set(toBounds);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Could not move pinned stack to bounds: " + toBounds, e);
+                }
+            });
+        }
+    }
+
+    /**
+     * @return the distance between points {@param p1} and {@param p2}.
+     */
+    private float distanceBetweenRectOffsets(Rect r1, Rect r2) {
+        return PointF.length(r1.left - r2.left, r1.top - r2.top);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 10393c6..b3adee0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -16,21 +16,10 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 
-import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
-import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.app.ActivityManager.StackInfo;
 import android.app.IActivityManager;
 import android.content.Context;
-import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -47,8 +36,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.policy.PipMotionHelper;
 import com.android.internal.policy.PipSnapAlgorithm;
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -60,24 +47,15 @@
  */
 public class PipTouchHandler implements TunerService.Tunable {
     private static final String TAG = "PipTouchHandler";
-    private static final boolean DEBUG_ALLOW_OUT_OF_BOUNDS_STACK = false;
 
     // These values are used for metrics and should never change
     private static final int METRIC_VALUE_DISMISSED_BY_TAP = 0;
     private static final int METRIC_VALUE_DISMISSED_BY_DRAG = 1;
 
     private static final String TUNER_KEY_DRAG_TO_DISMISS = "pip_drag_to_dismiss";
-    private static final String TUNER_KEY_ALLOW_MINIMIZE = "pip_allow_minimize";
 
-    private static final int SNAP_STACK_DURATION = 225;
-    private static final int DISMISS_STACK_DURATION = 375;
-    private static final int EXPAND_STACK_DURATION = 225;
-    private static final int MINIMIZE_STACK_MAX_DURATION = 200;
     private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200;
 
-    // The fraction of the stack width that the user has to drag offscreen to minimize the PIP
-    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
-
     private final Context mContext;
     private final IActivityManager mActivityManager;
     private final IWindowManager mWindowManager;
@@ -86,34 +64,28 @@
     private IPinnedStackController mPinnedStackController;
 
     private PipInputEventReceiver mInputEventReceiver;
-    private PipMenuActivityController mMenuController;
-    private PipDismissViewController mDismissViewController;
+    private final PipMenuActivityController mMenuController;
+    private final PipDismissViewController mDismissViewController;
     private final PipSnapAlgorithm mSnapAlgorithm;
-    private PipMotionHelper mMotionHelper;
 
     // Allow dragging the PIP to a location to close it
     private boolean mEnableDragToDismiss = false;
-    // Allow the PIP to be "docked" slightly offscreen
-    private boolean mEnableMinimizing = true;
 
-    private final Rect mStableInsets = new Rect();
-    private final Rect mPinnedStackBounds = new Rect();
-    private final Rect mBoundedPinnedStackBounds = new Rect();
-    private ValueAnimator mPinnedStackBoundsAnimator = null;
-    private ValueAnimator.AnimatorUpdateListener mUpdatePinnedStackBoundsListener =
-            new AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            mPinnedStackBounds.set((Rect) animation.getAnimatedValue());
-        }
-    };
+    // The current movement bounds
+    private Rect mMovementBounds = new Rect();
+
+    // The reference bounds used to calculate the normal/expanded target bounds
+    private Rect mNormalBounds = new Rect();
+    private Rect mNormalMovementBounds = new Rect();
+    private Rect mExpandedBounds = new Rect();
+    private Rect mExpandedMovementBounds = new Rect();
 
     private Handler mHandler = new Handler();
     private Runnable mShowDismissAffordance = new Runnable() {
         @Override
         public void run() {
             if (mEnableDragToDismiss) {
-                mDismissViewController.showDismissTarget(mPinnedStackBounds);
+                mDismissViewController.showDismissTarget(mMotionHelper.getBounds());
             }
         }
     };
@@ -121,13 +93,18 @@
     // Behaviour states
     private boolean mIsTappingThrough;
     private boolean mIsMinimized;
+    private boolean mIsMenuVisible;
+    private boolean mIsImeShowing;
+    private int mImeHeight;
+    private float mSavedSnapFraction = -1f;
 
     // Touch state
     private final PipTouchState mTouchState;
     private final FlingAnimationUtils mFlingAnimationUtils;
     private final PipTouchGesture[] mGestures;
+    private final PipMotionHelper mMotionHelper;
 
-    // Temporary vars
+    // Temp vars
     private final Rect mTmpBounds = new Rect();
 
     /**
@@ -160,32 +137,25 @@
     private class PipMenuListener implements PipMenuActivityController.Listener {
         @Override
         public void onPipMenuVisibilityChanged(boolean visible) {
-            if (!visible) {
-                mIsTappingThrough = false;
-                registerInputConsumer();
-            } else {
-                unregisterInputConsumer();
-            }
-            MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
-                    visible);
+            setMenuVisibilityState(visible);
         }
 
         @Override
         public void onPipExpand() {
             if (!mIsMinimized) {
-                expandPinnedStackToFullscreen();
+                mMotionHelper.expandPip();
             }
         }
 
         @Override
         public void onPipMinimize() {
-            setMinimizedState(true);
-            animateToClosestMinimizedTarget();
+            setMinimizedStateInternal(true);
+            mMotionHelper.animateToClosestMinimizedState(mMovementBounds, mMenuController);
         }
 
         @Override
         public void onPipDismiss() {
-            BackgroundThread.getHandler().post(PipTouchHandler.this::dismissPinnedStack);
+            mMotionHelper.dismissPip();
             MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
                     METRIC_VALUE_DISMISSED_BY_TAP);
         }
@@ -208,13 +178,12 @@
         mGestures = new PipTouchGesture[] {
                 mDefaultMovementGesture
         };
-        mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
+        mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mSnapAlgorithm,
+                mFlingAnimationUtils);
         registerInputConsumer();
-        setSnapToEdge(true);
 
         // Register any tuner settings changes
-        Dependency.get(TunerService.class).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS,
-                TUNER_KEY_ALLOW_MINIMIZE);
+        Dependency.get(TunerService.class).addTunable(this, TUNER_KEY_DRAG_TO_DISMISS);
     }
 
     @Override
@@ -222,17 +191,12 @@
         if (newValue == null) {
             // Reset back to default
             mEnableDragToDismiss = false;
-            mEnableMinimizing = true;
-            setMinimizedState(false);
             return;
         }
         switch (key) {
             case TUNER_KEY_DRAG_TO_DISMISS:
                 mEnableDragToDismiss = Integer.parseInt(newValue) != 0;
                 break;
-            case TUNER_KEY_ALLOW_MINIMIZE:
-                mEnableMinimizing = Integer.parseInt(newValue) != 0;
-                break;
         }
     }
 
@@ -243,26 +207,70 @@
             registerInputConsumer();
         }
         if (mIsMinimized) {
-            setMinimizedState(false);
+            setMinimizedStateInternal(false);
         }
     }
 
     public void onConfigurationChanged() {
-        mSnapAlgorithm.onConfigurationChanged();
-        updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */);
+        mMotionHelper.onConfigurationChanged();
+        mMotionHelper.synchronizePinnedStackBounds();
     }
 
-    public void onMinimizedStateChanged(boolean isMinimized) {
-        if (mIsMinimized != isMinimized) {
-            MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MINIMIZED,
-                    isMinimized);
+    public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+        mIsImeShowing = imeVisible;
+        mImeHeight = imeHeight;
+    }
+
+    public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+            boolean fromImeAdjustement) {
+        // Re-calculate the expanded bounds
+        mNormalBounds = normalBounds;
+        Rect normalMovementBounds = new Rect();
+        mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds,
+                mIsImeShowing ? mImeHeight : 0);
+        // TODO: Figure out the expanded size policy
+        mExpandedBounds = new Rect(normalBounds);
+        Rect expandedMovementBounds = new Rect();
+        mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
+                mIsImeShowing ? mImeHeight : 0);
+
+
+        // If this is from an IME adjustment, then we should move the PiP so that it is not occluded
+        // by the IME
+        if (fromImeAdjustement) {
+            if (mTouchState.isUserInteracting()) {
+                // Defer the update of the current movement bounds until after the user finishes
+                // touching the screen
+            } else {
+                final Rect bounds = new Rect(mMotionHelper.getBounds());
+                final Rect toMovementBounds = mIsMenuVisible
+                        ? expandedMovementBounds
+                        : normalMovementBounds;
+                if (mIsImeShowing) {
+                    // IME visible
+                    if (bounds.top == mMovementBounds.bottom) {
+                        // If the PIP is currently resting on top of the IME, then adjust it with
+                        // the hiding IME
+                        bounds.offsetTo(bounds.left, toMovementBounds.bottom);
+                    } else {
+                        bounds.offset(0, Math.min(0, toMovementBounds.bottom - bounds.top));
+                    }
+                } else {
+                    // IME hidden
+                    if (bounds.top == mMovementBounds.bottom) {
+                        // If the PIP is resting on top of the IME, then adjust it with the hiding IME
+                        bounds.offsetTo(bounds.left, toMovementBounds.bottom);
+                    }
+                }
+                mMotionHelper.animateToBounds(bounds);
+            }
         }
-        mIsMinimized = isMinimized;
-        mSnapAlgorithm.setMinimized(isMinimized);
-    }
 
-    public void onSnapToEdgeStateChanged(boolean isSnapToEdge) {
-        mSnapAlgorithm.setSnapToEdge(isSnapToEdge);
+        // Update the movement bounds after doing the calculations based on the old movement bounds
+        // above
+        mNormalMovementBounds = normalMovementBounds;
+        mExpandedMovementBounds = expandedMovementBounds;
+        updateMovementBounds();
     }
 
     private boolean handleTouchEvent(MotionEvent ev) {
@@ -276,20 +284,11 @@
 
         switch (ev.getAction()) {
             case MotionEvent.ACTION_DOWN: {
-                // Cancel any existing animations on the pinned stack
-                if (mPinnedStackBoundsAnimator != null) {
-                    mPinnedStackBoundsAnimator.cancel();
-                }
+                mMotionHelper.synchronizePinnedStackBounds();
 
-                updateBoundedPinnedStackBounds(true /* updatePinnedStackBounds */);
                 for (PipTouchGesture gesture : mGestures) {
                     gesture.onDown(mTouchState);
                 }
-                try {
-                    mPinnedStackController.setInInteractiveMode(true);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Could not set dragging state", e);
-                }
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -303,7 +302,7 @@
             case MotionEvent.ACTION_UP: {
                 // Update the movement bounds again if the state has changed since the user started
                 // dragging (ie. when the IME shows)
-                updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */);
+                updateMovementBounds();
 
                 for (PipTouchGesture gesture : mGestures) {
                     if (gesture.onUp(mTouchState)) {
@@ -314,11 +313,6 @@
                 // Fall through to clean up
             }
             case MotionEvent.ACTION_CANCEL: {
-                try {
-                    mPinnedStackController.setInInteractiveMode(false);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Could not set dragging state", e);
-                }
                 break;
             }
         }
@@ -326,16 +320,6 @@
     }
 
     /**
-     * @return whether the current touch state places the pip partially offscreen.
-     */
-    private boolean isDraggingOffscreen(PipTouchState touchState) {
-        PointF lastDelta = touchState.getLastTouchDelta();
-        PointF downDelta = touchState.getDownTouchDelta();
-        float left = mPinnedStackBounds.left + lastDelta.x;
-        return !(mBoundedPinnedStackBounds.left <= left && left <= mBoundedPinnedStackBounds.right);
-    }
-
-    /**
      * Registers the input consumer.
      */
     private void registerInputConsumer() {
@@ -374,27 +358,30 @@
     }
 
     /**
-     * Sets the snap-to-edge state and notifies the controller.
+     * Sets the minimized state.
      */
-    private void setSnapToEdge(boolean snapToEdge) {
-        onSnapToEdgeStateChanged(snapToEdge);
-
-        if (mPinnedStackController != null) {
-            try {
-                mPinnedStackController.setSnapToEdge(snapToEdge);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Could not set snap mode to edge", e);
-            }
-        }
+    void setMinimizedStateInternal(boolean isMinimized) {
+        setMinimizedState(isMinimized, false /* fromController */);
     }
 
     /**
-     * Sets the minimized state and notifies the controller.
+     * Sets the minimized state.
      */
-    private void setMinimizedState(boolean isMinimized) {
-        onMinimizedStateChanged(isMinimized);
+    void setMinimizedState(boolean isMinimized, boolean fromController) {
+        if (mIsMinimized != isMinimized) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MINIMIZED,
+                    isMinimized);
+        }
+        mIsMinimized = isMinimized;
+        mSnapAlgorithm.setMinimized(isMinimized);
 
-        if (mPinnedStackController != null) {
+        if (fromController) {
+            if (isMinimized) {
+                // Move the PiP to the new bounds immediately if minimized
+                mMotionHelper.movePip(mMotionHelper.getClosestMinimizedBounds(mNormalBounds,
+                        mMovementBounds));
+            }
+        } else if (mPinnedStackController != null) {
             try {
                 mPinnedStackController.setIsMinimized(isMinimized);
             } catch (RemoteException e) {
@@ -404,178 +391,43 @@
     }
 
     /**
-     * @return whether the given {@param pinnedStackBounds} indicates the PIP should be minimized.
+     * Sets the menu visibility.
      */
-    private boolean shouldMinimizedPinnedStack() {
-        Point displaySize = new Point();
-        mContext.getDisplay().getRealSize(displaySize);
-        if (mPinnedStackBounds.left < 0) {
-            float offscreenFraction = (float) -mPinnedStackBounds.left / mPinnedStackBounds.width();
-            return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION;
-        } else if (mPinnedStackBounds.right > displaySize.x) {
-            float offscreenFraction = (float) (mPinnedStackBounds.right - displaySize.x) /
-                    mPinnedStackBounds.width();
-            return offscreenFraction >= MINIMIZE_OFFSCREEN_FRACTION;
+    void setMenuVisibilityState(boolean isMenuVisible) {
+        if (!isMenuVisible) {
+            mIsTappingThrough = false;
+            registerInputConsumer();
         } else {
-            return false;
+            unregisterInputConsumer();
         }
-    }
+        MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
+                isMenuVisible);
 
-    /**
-     * Flings the minimized PIP to the closest minimized snap target.
-     */
-    private void flingToMinimizedSnapTarget(float velocityY) {
-        // We currently only allow flinging the minimized stack up and down, so just lock the
-        // movement bounds to the current stack bounds horizontally
-        Rect movementBounds = new Rect(mPinnedStackBounds.left, mBoundedPinnedStackBounds.top,
-                mPinnedStackBounds.left, mBoundedPinnedStackBounds.bottom);
-        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(movementBounds, mPinnedStackBounds,
-                0 /* velocityX */, velocityY);
-        if (!mPinnedStackBounds.equals(toBounds)) {
-            mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
-                    toBounds, 0, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener);
-            mFlingAnimationUtils.apply(mPinnedStackBoundsAnimator, 0,
-                    distanceBetweenRectOffsets(mPinnedStackBounds, toBounds),
-                    velocityY);
-            mPinnedStackBoundsAnimator.start();
-        }
-    }
-
-    /**
-     * Animates the PIP to the minimized state, slightly offscreen.
-     */
-    private void animateToClosestMinimizedTarget() {
-        Point displaySize = new Point();
-        mContext.getDisplay().getRealSize(displaySize);
-        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds,
-                mPinnedStackBounds);
-        mSnapAlgorithm.applyMinimizedOffset(toBounds, mBoundedPinnedStackBounds, displaySize,
-                mStableInsets);
-        mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
-                toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN,
-                mUpdatePinnedStackBoundsListener);
-        mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mMenuController.hideMenu();
+        if (isMenuVisible != mIsMenuVisible) {
+            if (isMenuVisible) {
+                // Save the current snap fraction and if we do not drag or move the PiP, then
+                // we store back to this snap fraction.  Otherwise, we'll reset the snap
+                // fraction and snap to the closest edge
+                Rect expandedBounds = new Rect(mExpandedBounds);
+                mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
+                        mMovementBounds, mExpandedMovementBounds);
+            } else {
+                // Try and restore the PiP to the closest edge, using the saved snap fraction
+                // if possible
+                Rect normalBounds = new Rect(mNormalBounds);
+                mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
+                        mNormalMovementBounds);
             }
-        });
-        mPinnedStackBoundsAnimator.start();
-    }
-
-    /**
-     * Flings the PIP to the closest snap target.
-     */
-    private Rect flingToSnapTarget(float velocity, float velocityX, float velocityY) {
-        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds,
-                mPinnedStackBounds, velocityX, velocityY);
-        if (!mPinnedStackBounds.equals(toBounds)) {
-            mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
-                toBounds, 0, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener);
-            mFlingAnimationUtils.apply(mPinnedStackBoundsAnimator, 0,
-                distanceBetweenRectOffsets(mPinnedStackBounds, toBounds),
-                velocity);
-            mPinnedStackBoundsAnimator.start();
-        }
-        return toBounds;
-    }
-
-    /**
-     * Animates the PIP to the closest snap target.
-     */
-    private Rect animateToClosestSnapTarget() {
-        Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds,
-                mPinnedStackBounds);
-        if (!mPinnedStackBounds.equals(toBounds)) {
-            mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
-                toBounds, SNAP_STACK_DURATION, FAST_OUT_SLOW_IN, mUpdatePinnedStackBoundsListener);
-            mPinnedStackBoundsAnimator.start();
-        }
-        return toBounds;
-    }
-
-    /**
-     * Animates the dismissal of the PIP over the dismiss target bounds.
-     */
-    private void animateDismissPinnedStack(Rect dismissBounds) {
-        Rect toBounds = new Rect(dismissBounds.centerX(),
-            dismissBounds.centerY(),
-            dismissBounds.centerX() + 1,
-            dismissBounds.centerY() + 1);
-        mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
-            toBounds, DISMISS_STACK_DURATION, FAST_OUT_LINEAR_IN, mUpdatePinnedStackBoundsListener);
-        mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                BackgroundThread.getHandler().post(PipTouchHandler.this::dismissPinnedStack);
-            }
-        });
-        mPinnedStackBoundsAnimator.start();
-    }
-
-    /**
-     * Resizes the pinned stack back to fullscreen.
-     */
-    void expandPinnedStackToFullscreen() {
-        BackgroundThread.getHandler().post(() -> {
-            try {
-                mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
-                        true /* allowResizeInDockedMode */, true /* preserveWindows */,
-                        true /* animate */, EXPAND_STACK_DURATION);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error showing PIP menu activity", e);
-            }
-        });
-    }
-
-    /**
-     * Tries to the move the pinned stack to the given {@param bounds}.
-     */
-    private void movePinnedStack(Rect bounds) {
-        if (!bounds.equals(mPinnedStackBounds)) {
-            mPinnedStackBounds.set(bounds);
-            if (mEnableDragToDismiss) {
-                mDismissViewController.updateDismissTarget(bounds);
-            }
-            mMotionHelper.resizeToBounds(mPinnedStackBounds);
+            mIsMenuVisible = isMenuVisible;
+            updateMovementBounds();
         }
     }
 
     /**
-     * Dismisses the pinned stack.
+     * @return the motion helper.
      */
-    private void dismissPinnedStack() {
-        try {
-            mActivityManager.removeStack(PINNED_STACK_ID);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to remove PIP", e);
-        }
-    }
-
-    /**
-     * Updates the movement bounds of the pinned stack.
-     */
-    private void updateBoundedPinnedStackBounds(boolean updatePinnedStackBounds) {
-        try {
-            StackInfo info = mActivityManager.getStackInfo(PINNED_STACK_ID);
-            if (info != null) {
-                if (updatePinnedStackBounds) {
-                    mPinnedStackBounds.set(info.bounds);
-                }
-                mWindowManager.getStableInsets(info.displayId, mStableInsets);
-                mBoundedPinnedStackBounds.set(mWindowManager.getPictureInPictureMovementBounds(
-                        info.displayId));
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch PIP movement bounds.", e);
-        }
-    }
-
-    /**
-     * @return the distance between points {@param p1} and {@param p2}.
-     */
-    private float distanceBetweenRectOffsets(Rect r1, Rect r2) {
-        return PointF.length(r1.left - r2.left, r1.top - r2.top);
+    public PipMotionHelper getMotionHelper() {
+        return mMotionHelper;
     }
 
     /**
@@ -593,25 +445,31 @@
 
         @Override
         boolean onMove(PipTouchState touchState) {
+            if (touchState.startedDragging()) {
+                mSavedSnapFraction = -1f;
+            }
+
             if (touchState.startedDragging() && mEnableDragToDismiss) {
                 mHandler.removeCallbacks(mShowDismissAffordance);
-                mDismissViewController.showDismissTarget(mPinnedStackBounds);
+                mDismissViewController.showDismissTarget(mMotionHelper.getBounds());
             }
 
             if (touchState.isDragging()) {
                 // Move the pinned stack freely
-                PointF lastDelta = touchState.getLastTouchDelta();
-                float left = mPinnedStackBounds.left + lastDelta.x;
-                float top = mPinnedStackBounds.top + lastDelta.y;
+                mTmpBounds.set(mMotionHelper.getBounds());
+                final PointF lastDelta = touchState.getLastTouchDelta();
+                float left = mTmpBounds.left + lastDelta.x;
+                float top = mTmpBounds.top + lastDelta.y;
                 if (!touchState.allowDraggingOffscreen()) {
-                    left = Math.max(mBoundedPinnedStackBounds.left, Math.min(
-                            mBoundedPinnedStackBounds.right, left));
+                    left = Math.max(mMovementBounds.left, Math.min(mMovementBounds.right, left));
                 }
-                top = Math.max(mBoundedPinnedStackBounds.top, Math.min(
-                        mBoundedPinnedStackBounds.bottom, top));
-                mTmpBounds.set(mPinnedStackBounds);
+                top = Math.max(mMovementBounds.top, Math.min(mMovementBounds.bottom, top));
                 mTmpBounds.offsetTo((int) left, (int) top);
-                movePinnedStack(mTmpBounds);
+                mMotionHelper.movePip(mTmpBounds);
+
+                if (mEnableDragToDismiss) {
+                    mDismissViewController.updateDismissTarget(mTmpBounds);
+                }
                 return true;
             }
             return false;
@@ -626,9 +484,12 @@
                     final float velocity = PointF.length(vel.x, vel.y);
                     if (touchState.isDragging()
                             && velocity < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
-                        if (mDismissViewController.shouldDismiss(mPinnedStackBounds)) {
+                        if (mDismissViewController.shouldDismiss(mMotionHelper.getBounds())) {
                             Rect dismissBounds = mDismissViewController.getDismissBounds();
-                            animateDismissPinnedStack(dismissBounds);
+                            mMotionHelper.animateDismissFromDrag(dismissBounds);
+                            MetricsLogger.action(mContext,
+                                    MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
+                                    METRIC_VALUE_DISMISSED_BY_DRAG);
                             return true;
                         }
                     }
@@ -638,34 +499,34 @@
             }
             if (touchState.isDragging()) {
                 PointF vel = mTouchState.getVelocity();
-                if (!mIsMinimized && (shouldMinimizedPinnedStack()
+                if (!mIsMinimized && (mMotionHelper.shouldMinimizePip()
                         || isHorizontalFlingTowardsCurrentEdge(vel))) {
                     // Pip should be minimized
-                    setMinimizedState(true);
-                    animateToClosestMinimizedTarget();
+                    setMinimizedStateInternal(true);
+                    mMotionHelper.animateToClosestMinimizedState(mMovementBounds, mMenuController);
                     return true;
                 }
                 if (mIsMinimized) {
                     // If we're dragging and it wasn't a minimize gesture
                     // then we shouldn't be minimized.
-                    setMinimizedState(false);
+                    setMinimizedStateInternal(false);
                 }
 
                 final float velocity = PointF.length(vel.x, vel.y);
                 if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
-                    flingToSnapTarget(velocity, vel.x, vel.y);
+                    mMotionHelper.flingToSnapTarget(velocity, vel.x, vel.y, mMovementBounds);
                 } else {
-                    animateToClosestSnapTarget();
+                    mMotionHelper.animateToClosestSnapTarget(mMovementBounds);
                 }
             } else if (mIsMinimized) {
                 // This was a tap, so no longer minimized
-                animateToClosestSnapTarget();
-                setMinimizedState(false);
+                mMotionHelper.animateToClosestSnapTarget(mMovementBounds);
+                setMinimizedStateInternal(false);
             } else if (!mIsTappingThrough) {
                 mMenuController.showMenu();
                 mIsTappingThrough = true;
             } else {
-                expandPinnedStackToFullscreen();
+                mMotionHelper.expandPip();
             }
             return true;
         }
@@ -679,17 +540,30 @@
         final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
         final boolean isFling = PointF.length(vel.x, vel.y) > mFlingAnimationUtils
                 .getMinVelocityPxPerSecond();
-        final boolean towardsCurrentEdge = onEdge(true /* left */) && vel.x < 0
-                || onEdge(false /* right */) && vel.x > 0;
+        final boolean towardsCurrentEdge = isOverEdge(true /* left */) && vel.x < 0
+                || isOverEdge(false /* right */) && vel.x > 0;
         return towardsCurrentEdge && isHorizontal && isFling;
     }
 
-    private boolean onEdge(boolean checkLeft) {
+    /**
+     * @return whether the given bounds are on the left or right edge (depending on
+     *         {@param checkLeft})
+     */
+    private boolean isOverEdge(boolean checkLeft) {
+        final Rect bounds = mMotionHelper.getBounds();
         if (checkLeft) {
-            return mPinnedStackBounds.left <= mBoundedPinnedStackBounds.left;
+            return bounds.left <= mMovementBounds.left;
         } else {
-            return mPinnedStackBounds.right >= mBoundedPinnedStackBounds.right
-                    + mPinnedStackBounds.width();
+            return bounds.right >= mMovementBounds.right + bounds.width();
         }
     }
+
+    /**
+     * Updates the current movement bounds based on whether the menu is currently visible.
+     */
+    private void updateMovementBounds() {
+        mMovementBounds = mIsMenuVisible
+                ? mExpandedMovementBounds
+                : mNormalMovementBounds;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index 2e84ced..868b34b7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -34,6 +34,7 @@
     private final PointF mLastTouch = new PointF();
     private final PointF mLastDelta = new PointF();
     private final PointF mVelocity = new PointF();
+    private boolean mIsUserInteracting = false;
     private boolean mIsDragging = false;
     private boolean mStartedDragging = false;
     private boolean mAllowDraggingOffscreen = false;
@@ -57,6 +58,7 @@
                 mIsDragging = false;
                 mStartedDragging = false;
                 mAllowDraggingOffscreen = true;
+                mIsUserInteracting = true;
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -107,6 +109,7 @@
                 // Fall through to clean up
             }
             case MotionEvent.ACTION_CANCEL: {
+                mIsUserInteracting = false;
                 recycleVelocityTracker();
                 break;
             }
@@ -151,6 +154,13 @@
     }
 
     /**
+     * @return whether the user is currently interacting with the PiP.
+     */
+    public boolean isUserInteracting() {
+        return mIsUserInteracting;
+    }
+
+    /**
      * @return whether the user has started dragging just in the last handled touch event.
      */
     public boolean startedDragging() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 964fefa..cf7b05e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.media.session.MediaController;
@@ -39,6 +40,8 @@
 import android.util.Log;
 import android.util.Pair;
 import android.view.Display;
+import android.view.IPinnedStackController;
+import android.view.IPinnedStackListener;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -51,6 +54,8 @@
 import java.util.List;
 
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import static com.android.systemui.Prefs.Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN;
 
 /**
@@ -159,6 +164,8 @@
     private boolean mOnboardingShown;
     private String[] mLastPackagesResourceGranted;
 
+    private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
+
     private final Runnable mResizePinnedStackRunnable = new Runnable() {
         @Override
         public void run() {
@@ -196,6 +203,32 @@
                 }
             };
 
+    /**
+     * Handler for messages from the PIP controller.
+     */
+    private class PinnedStackListener extends IPinnedStackListener.Stub {
+
+        @Override
+        public void onListenerRegistered(IPinnedStackController controller) {}
+
+        @Override
+        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {}
+
+        @Override
+        public void onMinimizedStateChanged(boolean isMinimized) {}
+
+        @Override
+        public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+                boolean fromImeAdjustement) {
+            mHandler.post(() -> {
+                mDefaultPipBounds.set(normalBounds);
+            });
+        }
+
+        @Override
+        public void onActionsChanged(ParceledListSlice actions) {}
+    }
+
     private PipManager() { }
 
     /**
@@ -221,16 +254,16 @@
         mPipRecentsOverlayManager = new PipRecentsOverlayManager(context);
         mMediaSessionManager =
                 (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
+
+        try {
+            mWindowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to register pinned stack listener", e);
+        }
     }
 
     private void loadConfigurationsAndApply() {
         Resources res = mContext.getResources();
-        try {
-            mDefaultPipBounds = mWindowManager.getPictureInPictureDefaultBounds(
-                    Display.DEFAULT_DISPLAY);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to get default PIP bounds", e);
-        }
         mSettingsPipBounds = Rect.unflattenFromString(res.getString(
                 R.string.pip_settings_bounds));
         mMenuModePipBounds = Rect.unflattenFromString(res.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index a5a1eaa..3b9e7bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -99,8 +99,9 @@
             record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
             previousView = record.tileView.updateAccessibilityOrder(previousView);
         }
-        setMeasuredDimension(width,
-                (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin));
+        int height = (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin);
+        if (height < 0) height = 0;
+        setMeasuredDimension(width, height);
     }
 
     private static int exactly(int size) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 3afbc35..dea56aa1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -237,6 +237,8 @@
         i.setPackage(mComponent.getPackageName());
         i = resolveIntent(i);
         if (i != null) {
+            i.putExtra(TileService.EXTRA_COMPONENT, mComponent);
+            i.putExtra(TileService.EXTRA_STATE, mTile.getState());
             return i;
         }
         return new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 70f8109..dab5967 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.UserManager;
@@ -37,6 +40,9 @@
 
 /** Quick settings tile: Hotspot **/
 public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> {
+    static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
+             "com.android.settings", "com.android.settings.TetherSettings"));
+
     private final AnimationIcon mEnable =
             new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
                     R.drawable.ic_hotspot_disable);
@@ -94,7 +100,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        return new Intent(Settings.ACTION_WIRELESS_SETTINGS);
+        return new Intent(TETHER_SETTINGS);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 9157e33..e635162 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -205,7 +205,6 @@
         sTaskLoader = new RecentsTaskLoader(mContext);
         sConfiguration = new RecentsConfiguration(mContext);
         mHandler = new Handler();
-        getComponent(CommandQueue.class).addCallbacks(this);
         UiModeManager uiModeManager = (UiModeManager) mContext.
                 getSystemService(Context.UI_MODE_SERVICE);
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
@@ -234,6 +233,7 @@
         if (sSystemServicesProxy.isSystemUser(processUser)) {
             // For the system user, initialize an instance of the interface that we can pass to the
             // secondary user
+            getComponent(CommandQueue.class).addCallbacks(this);
             mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
         } else {
             // For the secondary user, bind to the primary user's service to get a persistent
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 609e3fb..8091199 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -76,6 +76,7 @@
 import com.android.systemui.recents.views.TaskStackViewScroller;
 import com.android.systemui.recents.views.TaskViewHeader;
 import com.android.systemui.recents.views.TaskViewTransform;
+import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
 import com.android.systemui.stackdivider.DividerView;
 import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -637,10 +638,21 @@
             stackLayout.initialize(displayRect, windowRect, mTaskStackBounds,
                     TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
             mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
+            // Get the width of a task view so that we know how wide to draw the header bar.
+            int taskViewWidth = 0;
+            if (mDummyStackView.useGridLayout()) {
+                TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm();
+                gridLayout.initialize(windowRect);
+                taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */,
+                        stack.getTaskCount(), new TaskViewTransform(), stackLayout).rect.width();
+            } else {
+                Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
+                if (!taskViewBounds.isEmpty()) {
+                    taskViewWidth = taskViewBounds.width();
+                }
+            }
 
-            Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
-            if (!taskViewBounds.isEmpty()) {
-                int taskViewWidth = taskViewBounds.width();
+            if (taskViewWidth > 0) {
                 synchronized (mHeaderBarLock) {
                     if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
                             mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index fb94c7e..0160eb7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -96,6 +96,7 @@
 import com.android.systemui.recents.model.TaskStack;
 
 import com.android.systemui.recents.views.grid.GridTaskView;
+import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
 import com.android.systemui.recents.views.grid.TaskViewFocusFrame;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -447,6 +448,11 @@
         return mLayoutAlgorithm;
     }
 
+    /** Returns the grid algorithm for this task stack. */
+    public TaskGridLayoutAlgorithm getGridAlgorithm() {
+        return mLayoutAlgorithm.mTaskGridLayoutAlgorithm;
+    }
+
     /**
      * Returns the touch handler for this task stack.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index b9a0f74..0b09acc 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -72,6 +72,10 @@
         return mMinimized;
     }
 
+    public boolean isHomeStackResizable() {
+        return mHomeStackResizable;
+    }
+
     private void addDivider(Configuration configuration) {
         mView = (DividerView)
                 LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
@@ -119,6 +123,7 @@
         mView.post(new Runnable() {
             @Override
             public void run() {
+                mHomeStackResizable = isHomeStackResizable;
                 if (mMinimized != minimized) {
                     mMinimized = minimized;
                     updateTouchable();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 49035ba..6f59fe2 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -1241,7 +1241,8 @@
 
     public final void onBusEvent(UndockingTaskEvent undockingTaskEvent) {
         int dockSide = mWindowManagerProxy.getDockSide();
-        if (dockSide != WindowManager.DOCKED_INVALID && !mDockedStackMinimized) {
+        if (dockSide != WindowManager.DOCKED_INVALID && (mHomeStackResizable
+                || !mDockedStackMinimized)) {
             startDragging(false /* animate */, false /* touching */);
             SnapTarget target = dockSideTopLeft(dockSide)
                     ? mSnapAlgorithm.getDismissEndTarget()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 4b1baa2..0bd6491 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -105,7 +105,7 @@
     private boolean mDimmed;
     private boolean mDark;
 
-    private int mBgTint = NO_COLOR;
+    protected int mBgTint = NO_COLOR;
     private float mBgAlpha = 1f;
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 477701c..9245df0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -63,9 +63,6 @@
     private static final int MSG_SET_WINDOW_STATE              = 12 << MSG_SHIFT;
     private static final int MSG_SHOW_RECENT_APPS              = 13 << MSG_SHIFT;
     private static final int MSG_HIDE_RECENT_APPS              = 14 << MSG_SHIFT;
-    private static final int MSG_BUZZ_BEEP_BLINKED             = 15 << MSG_SHIFT;
-    private static final int MSG_NOTIFICATION_LIGHT_OFF        = 16 << MSG_SHIFT;
-    private static final int MSG_NOTIFICATION_LIGHT_PULSE      = 17 << MSG_SHIFT;
     private static final int MSG_SHOW_SCREEN_PIN_REQUEST       = 18 << MSG_SHIFT;
     private static final int MSG_APP_TRANSITION_PENDING        = 19 << MSG_SHIFT;
     private static final int MSG_APP_TRANSITION_CANCELLED      = 20 << MSG_SHIFT;
@@ -121,9 +118,6 @@
         default void toggleKeyboardShortcutsMenu(int deviceId) { }
         default void cancelPreloadRecentApps() { }
         default void setWindowState(int window, int state) { }
-        default void buzzBeepBlinked() { }
-        default void notificationLightOff() { }
-        default void notificationLightPulse(int argb, int onMillis, int offMillis) { }
         default void showScreenPinningRequest(int taskId) { }
         default void appTransitionPending() { }
         default void appTransitionCancelled() { }
@@ -313,26 +307,6 @@
         }
     }
 
-    public void buzzBeepBlinked() {
-        synchronized (mLock) {
-            mHandler.removeMessages(MSG_BUZZ_BEEP_BLINKED);
-            mHandler.sendEmptyMessage(MSG_BUZZ_BEEP_BLINKED);
-        }
-    }
-
-    public void notificationLightOff() {
-        synchronized (mLock) {
-            mHandler.sendEmptyMessage(MSG_NOTIFICATION_LIGHT_OFF);
-        }
-    }
-
-    public void notificationLightPulse(int argb, int onMillis, int offMillis) {
-        synchronized (mLock) {
-            mHandler.obtainMessage(MSG_NOTIFICATION_LIGHT_PULSE, onMillis, offMillis, argb)
-                    .sendToTarget();
-        }
-    }
-
     public void showScreenPinningRequest(int taskId) {
         synchronized (mLock) {
             mHandler.obtainMessage(MSG_SHOW_SCREEN_PIN_REQUEST, taskId, 0, null)
@@ -524,21 +498,6 @@
                         mCallbacks.get(i).setWindowState(msg.arg1, msg.arg2);
                     }
                     break;
-                case MSG_BUZZ_BEEP_BLINKED:
-                    for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).buzzBeepBlinked();
-                    }
-                    break;
-                case MSG_NOTIFICATION_LIGHT_OFF:
-                    for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).notificationLightOff();
-                    }
-                    break;
-                case MSG_NOTIFICATION_LIGHT_PULSE:
-                    for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
-                    }
-                    break;
                 case MSG_SHOW_SCREEN_PIN_REQUEST:
                     for (int i = 0; i < mCallbacks.size(); i++) {
                         mCallbacks.get(i).showScreenPinningRequest(msg.arg1);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 85e2bd6..2e9c7fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1880,14 +1880,14 @@
             } else if (isUserLocked()) {
                 return mChildrenContainer.getGroupExpandFraction();
             }
-        } else if (isColorized()) {
+        } else if (isColorized() && (!mIsLowPriority || isExpanded())) {
             return -1.0f;
         }
         return 0.0f;
     }
 
     private boolean isColorized() {
-        return mIsColorized;
+        return mIsColorized && mBgTint != NO_COLOR;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e8e9d4e..2425076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -68,6 +68,7 @@
     private float mMaxShelfEnd;
     private int mRelativeOffset;
     private boolean mInteractive;
+    private boolean mAnimationsEnabled = true;
 
     public NotificationShelf(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -388,12 +389,13 @@
 
         View rowIcon = row.getNotificationIcon();
         float notificationIconPosition = row.getTranslationY() + row.getContentTranslation();
-        if (usingLinearInterpolation) {
+        boolean stayingInShelf = row.isInShelf() && !row.isTransformingIntoShelf();
+        if (usingLinearInterpolation && !stayingInShelf) {
             // If we interpolate from the notification position, this might lead to a slightly
             // odd interpolation, since the notification position changes as well. Let's interpolate
             // from a fixed distance. We can only do this if we don't animate and the icon is
             // always in the interpolated positon.
-            notificationIconPosition = mMaxShelfEnd - getIntrinsicHeight() - iconTransformDistance;
+            notificationIconPosition = getTranslationY() - iconTransformDistance;
         }
         float notificationIconSize = 0.0f;
         int iconTopPadding;
@@ -426,7 +428,7 @@
             iconState.hidden = transitionAmount == 0.0f;
             iconState.alpha = alpha;
             iconState.yTranslation = iconYTranslation;
-            if (row.isInShelf() && !row.isTransformingIntoShelf()) {
+            if (stayingInShelf) {
                 iconState.iconAppearAmount = 1.0f;
                 iconState.alpha = 1.0f;
                 iconState.scaleX = 1.0f;
@@ -573,6 +575,15 @@
         mMaxShelfEnd = maxShelfEnd;
     }
 
+    public void setAnimationsEnabled(boolean enabled) {
+        mAnimationsEnabled = enabled;
+        mCollapsedIcons.setAnimationsEnabled(enabled);
+        if (!enabled) {
+            // we need to wait with enabling the animations until the first frame has passed
+            mShelfIcons.setAnimationsEnabled(false);
+        }
+    }
+
     private class ShelfState extends ExpandableViewState {
         private float openedAmount;
         private boolean hasItemsInStableShelf;
@@ -585,6 +596,7 @@
             setOpenedAmount(openedAmount);
             updateAppearance();
             setHasItemsInStableShelf(hasItemsInStableShelf);
+            mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
         }
 
         @Override
@@ -594,6 +606,7 @@
             setOpenedAmount(openedAmount);
             updateAppearance();
             setHasItemsInStableShelf(hasItemsInStableShelf);
+            mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 03c7325..e5f32df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -105,6 +105,11 @@
     }
 
     @Override
+    protected boolean shouldClearBackgroundOnReapply() {
+        return false;
+    }
+
+    @Override
     public int getCustomBackgroundColor() {
         int customBackgroundColor = super.getCustomBackgroundColor();
         if (customBackgroundColor == 0 && mShowingLegacyBackground) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 836482a..5f5e1e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -93,7 +93,9 @@
     public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
         mDarkInitialized = false;
         Drawable background = mView.getBackground();
-        mBackgroundColor = 0;
+        if (shouldClearBackgroundOnReapply()) {
+            mBackgroundColor = 0;
+        }
         if (background instanceof ColorDrawable) {
             mBackgroundColor = ((ColorDrawable) background).getColor();
             mView.setBackground(null);
@@ -101,6 +103,10 @@
         mShouldInvertDark = mBackgroundColor == 0 || isColorLight(mBackgroundColor);
     }
 
+    protected boolean shouldClearBackgroundOnReapply() {
+        return true;
+    }
+
     private boolean isColorLight(int backgroundColor) {
         return Color.alpha(backgroundColor) == 0
                 || ColorUtils.calculateLuminance(backgroundColor) > 0.5;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 62b536e..808cd21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -23,6 +23,7 @@
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
 import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
 
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -79,6 +80,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.List;
 import java.util.Locale;
 
 /**
@@ -101,7 +103,7 @@
 
     private int mNavigationIconHints = 0;
     private int mNavigationBarMode;
-    protected AccessibilityManager mAccessibilityManager;
+    private AccessibilityManager mAccessibilityManager;
 
     private int mDisabledFlags1;
     private StatusBar mStatusBar;
@@ -132,6 +134,8 @@
         mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
         mWindowManager = getContext().getSystemService(WindowManager.class);
         mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
+        mAccessibilityManager.addAccessibilityServicesStateChangeListener(
+                this::updateAccessibilityServicesState);
         if (savedInstanceState != null) {
             mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
         }
@@ -149,6 +153,8 @@
     public void onDestroy() {
         super.onDestroy();
         mCommandQueue.removeCallbacks(this);
+        mAccessibilityManager.removeAccessibilityServicesStateChangeListener(
+                this::updateAccessibilityServicesState);
         try {
             WindowManagerGlobal.getWindowManagerService()
                     .removeRotationWatcher(mRotationWatcher);
@@ -402,6 +408,10 @@
         ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
         homeButton.setOnTouchListener(this::onHomeTouch);
         homeButton.setOnLongClickListener(this::onHomeLongClick);
+
+        ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
+        accessibilityButton.setOnClickListener(this::onAccessibilityClick);
+        accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
     }
 
     private boolean onHomeTouch(View v, MotionEvent event) {
@@ -553,6 +563,34 @@
                 MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
     }
 
+    private void onAccessibilityClick(View v) {
+        mAccessibilityManager.notifyAccessibilityButtonClicked();
+    }
+
+    private boolean onAccessibilityLongClick(View v) {
+        // TODO(b/34720082): Target service selection via long click
+        android.widget.Toast.makeText(getContext(), "Service selection coming soon...",
+                android.widget.Toast.LENGTH_LONG).show();
+        return true;
+    }
+
+    private void updateAccessibilityServicesState() {
+        final List<AccessibilityServiceInfo> services =
+                mAccessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+        int requestingServices = 0;
+        for (int i = services.size() - 1; i >= 0; --i) {
+            AccessibilityServiceInfo info = services.get(i);
+            if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0) {
+                requestingServices++;
+            }
+        }
+
+        final boolean showAccessibilityButton = requestingServices >= 1;
+        final boolean targetSelection = requestingServices >= 2;
+        mNavigationBarView.setAccessibilityButtonState(showAccessibilityButton, targetSelection);
+    }
+
     // ----- Methods that StatusBar talks to (should be minimized) -----
 
     public void setLightBarController(LightBarController lightBarController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index dced747..5d13289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -78,6 +78,8 @@
     private int mCurrentRotation = -1;
 
     boolean mShowMenu;
+    boolean mShowAccessibilityButton;
+    boolean mLongClickableAccessibilityButton;
     int mDisabledFlags = 0;
     int mNavigationIconHints = 0;
 
@@ -89,6 +91,7 @@
     private KeyButtonDrawable mDockedIcon;
     private KeyButtonDrawable mImeIcon;
     private KeyButtonDrawable mMenuIcon;
+    private KeyButtonDrawable mAccessibilityIcon;
 
     private GestureHelper mGestureHelper;
     private DeadZone mDeadZone;
@@ -202,6 +205,9 @@
         mVertical = false;
         mShowMenu = false;
 
+        mShowAccessibilityButton = false;
+        mLongClickableAccessibilityButton = false;
+
         mConfiguration = new Configuration();
         mConfiguration.updateFrom(context.getResources().getConfiguration());
         updateIcons(context, Configuration.EMPTY, mConfiguration);
@@ -213,6 +219,8 @@
         mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
         mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
         mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
+        mButtonDispatchers.put(R.id.accessibility_button,
+                new ButtonDispatcher(R.id.accessibility_button));
     }
 
     public BarTransitions getBarTransitions() {
@@ -287,6 +295,10 @@
         return mButtonDispatchers.get(R.id.ime_switcher);
     }
 
+    public ButtonDispatcher getAccessibilityButton() {
+        return mButtonDispatchers.get(R.id.accessibility_button);
+    }
+
     public SparseArray<ButtonDispatcher> getButtonDispatchers() {
         return mButtonDispatchers;
     }
@@ -320,6 +332,8 @@
             mRecentIcon = getDrawable(ctx,
                     R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
             mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
+            mAccessibilityIcon = getDrawable(ctx, R.drawable.ic_sysbar_accessibility_button,
+                    R.drawable.ic_sysbar_accessibility_button_dark);
 
             Context darkContext = new ContextThemeWrapper(ctx, R.style.DualToneDarkTheme);
             Context lightContext = new ContextThemeWrapper(ctx, R.style.DualToneLightTheme);
@@ -411,6 +425,9 @@
         setMenuVisibility(mShowMenu, true);
         getMenuButton().setImageDrawable(mMenuIcon);
 
+        setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
+        getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
+
         setDisabledFlags(mDisabledFlags, true);
 
         mBarTransitions.reapplyDarkIntensity();
@@ -517,13 +534,25 @@
 
         mShowMenu = show;
 
-        // Only show Menu if IME switcher not shown.
-        final boolean shouldShow = mShowMenu &&
+        // Only show Menu if IME switcher and Accessibility button not shown.
+        final boolean shouldShow = mShowMenu && !mShowAccessibilityButton &&
                 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
 
         getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
     }
 
+    public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
+        mShowAccessibilityButton = visible;
+        mLongClickableAccessibilityButton = longClickable;
+        if (visible) {
+            // Accessibility button overrides Menu button.
+            setMenuVisibility(false, true);
+        }
+
+        getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+        getAccessibilityButton().setLongClickable(longClickable);
+    }
+
     @Override
     public void onFinishInflate() {
         mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
@@ -814,6 +843,7 @@
         dumpButton(pw, "home", getHomeButton());
         dumpButton(pw, "rcnt", getRecentsButton());
         dumpButton(pw, "menu", getMenuButton());
+        dumpButton(pw, "a11y", getAccessibilityButton());
 
         pw.println("    }");
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index c25a45c..571ae26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -104,6 +104,7 @@
     private float mOpenedAmount = 0.0f;
     private float mVisualOverflowAdaption;
     private boolean mDisallowNextAnimation;
+    private boolean mAnimationsEnabled = true;
 
     public NotificationIconContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -255,7 +256,7 @@
             iconState.visibleState = StatusBarIconView.STATE_ICON;
             if (firstOverflowIndex == -1 && (isAmbient
                     || (translationX >= (noOverflowAfter ? layoutEnd - mIconSize : overflowStart)))) {
-                firstOverflowIndex = noOverflowAfter ? i - 1 : i;
+                firstOverflowIndex = noOverflowAfter && !isAmbient ? i - 1 : i;
                 int totalDotLength = mStaticDotRadius * 6 + 2 * mDotPadding;
                 visualOverflowStart = overflowStart + mIconSize * (1 + OVERFLOW_EARLY_AMOUNT)
                         - totalDotLength / 2
@@ -422,6 +423,20 @@
         return mIconSize;
     }
 
+    public void setAnimationsEnabled(boolean enabled) {
+        if (!enabled && mAnimationsEnabled) {
+            for (int i = 0; i < getChildCount(); i++) {
+                View child = getChildAt(i);
+                ViewState childState = mIconStates.get(child);
+                if (childState != null) {
+                    childState.cancelAnimations(child);
+                    childState.applyToView(child);
+                }
+            }
+        }
+        mAnimationsEnabled = enabled;
+    }
+
     public class IconState extends ViewState {
         public float iconAppearAmount = 1.0f;
         public float clampedAppearAmount = 1.0f;
@@ -438,52 +453,59 @@
                 StatusBarIconView icon = (StatusBarIconView) view;
                 boolean animate = false;
                 AnimationProperties animationProperties = null;
-                if (justAdded) {
-                    super.applyToView(icon);
-                    icon.setAlpha(0.0f);
-                    icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, false /* animate */);
-                    animationProperties = ADD_ICON_PROPERTIES;
-                    animate = true;
-                } else if (visibleState != icon.getVisibleState()) {
-                    animationProperties = DOT_ANIMATION_PROPERTIES;
-                    animate = true;
-                }
-                if (!animate && mAddAnimationStartIndex >= 0
-                        && indexOfChild(view) >= mAddAnimationStartIndex
-                        && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
-                            || visibleState != StatusBarIconView.STATE_HIDDEN)) {
-                    animationProperties = DOT_ANIMATION_PROPERTIES;
-                    animate = true;
-                }
-                if (needsCannedAnimation) {
-                    AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
-                    animationFilter.reset();
-                    animationFilter.combineFilter(ICON_ANIMATION_PROPERTIES.getAnimationFilter());
-                    mTempProperties.resetCustomInterpolators();
-                    mTempProperties.combineCustomInterpolators(ICON_ANIMATION_PROPERTIES);
-                    if (animationProperties != null) {
-                        animationFilter.combineFilter(animationProperties.getAnimationFilter());
-                        mTempProperties.combineCustomInterpolators(animationProperties);
+                boolean animationsAllowed = mAnimationsEnabled && !mDisallowNextAnimation;
+                if (animationsAllowed) {
+                    if (justAdded) {
+                        super.applyToView(icon);
+                        if (iconAppearAmount != 0.0f) {
+                            icon.setAlpha(0.0f);
+                            icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
+                                    false /* animate */);
+                            animationProperties = ADD_ICON_PROPERTIES;
+                            animate = true;
+                        }
+                    } else if (visibleState != icon.getVisibleState()) {
+                        animationProperties = DOT_ANIMATION_PROPERTIES;
+                        animate = true;
                     }
-                    animationProperties = mTempProperties;
-                    animationProperties.setDuration(CANNED_ANIMATION_DURATION);
-                    animate = true;
-                    mCannedAnimationStartIndex = indexOfChild(view);
+                    if (!animate && mAddAnimationStartIndex >= 0
+                            && indexOfChild(view) >= mAddAnimationStartIndex
+                            && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+                            || visibleState != StatusBarIconView.STATE_HIDDEN)) {
+                        animationProperties = DOT_ANIMATION_PROPERTIES;
+                        animate = true;
+                    }
+                    if (needsCannedAnimation) {
+                        AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+                        animationFilter.reset();
+                        animationFilter.combineFilter(
+                                ICON_ANIMATION_PROPERTIES.getAnimationFilter());
+                        mTempProperties.resetCustomInterpolators();
+                        mTempProperties.combineCustomInterpolators(ICON_ANIMATION_PROPERTIES);
+                        if (animationProperties != null) {
+                            animationFilter.combineFilter(animationProperties.getAnimationFilter());
+                            mTempProperties.combineCustomInterpolators(animationProperties);
+                        }
+                        animationProperties = mTempProperties;
+                        animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+                        animate = true;
+                        mCannedAnimationStartIndex = indexOfChild(view);
+                    }
+                    if (!animate && mCannedAnimationStartIndex >= 0
+                            && indexOfChild(view) > mCannedAnimationStartIndex
+                            && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+                            || visibleState != StatusBarIconView.STATE_HIDDEN)) {
+                        AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+                        animationFilter.reset();
+                        animationFilter.animateX();
+                        mTempProperties.resetCustomInterpolators();
+                        animationProperties = mTempProperties;
+                        animationProperties.setDuration(CANNED_ANIMATION_DURATION);
+                        animate = true;
+                    }
                 }
-                if (!animate && mCannedAnimationStartIndex >= 0
-                        && indexOfChild(view) > mCannedAnimationStartIndex
-                        && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
-                        || visibleState != StatusBarIconView.STATE_HIDDEN)) {
-                    AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
-                    animationFilter.reset();
-                    animationFilter.animateX();
-                    mTempProperties.resetCustomInterpolators();
-                    animationProperties = mTempProperties;
-                    animationProperties.setDuration(CANNED_ANIMATION_DURATION);
-                    animate = true;
-                }
-                icon.setVisibleState(visibleState);
-                if (animate && !mDisallowNextAnimation) {
+                icon.setVisibleState(visibleState, animationsAllowed);
+                if (animate) {
                     animateTo(icon, animationProperties);
                 } else {
                     super.applyToView(view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 638c12f..54c67d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -603,8 +603,6 @@
             new ArraySet<>();
     private long mLastVisibilityReportUptimeMs;
 
-    private final ShadeUpdates mShadeUpdates = new ShadeUpdates();
-
     private Runnable mLaunchTransitionEndRunnable;
     protected boolean mLaunchTransitionFadingAway;
     private ExpandableNotificationRow mDraggedDownRow;
@@ -1501,7 +1499,7 @@
                     ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction);
         } else {
             Divider divider = getComponent(Divider.class);
-            if (divider != null && divider.isMinimized()) {
+            if (divider != null && divider.isMinimized() && !divider.isHomeStackResizable()) {
                 // Undocking from the minimized state is not supported
                 return false;
             } else {
@@ -1894,7 +1892,6 @@
         updateEmptyShadeView();
 
         updateQsExpansionEnabled();
-        mShadeUpdates.check();
 
         // Let's also update the icons
         mIconController.updateNotificationIcons(mNotificationData);
@@ -3071,24 +3068,6 @@
     }
 
     @Override // CommandQueue
-    public void buzzBeepBlinked() {
-    }
-
-    @Override
-    public void notificationLightOff() {
-        if (mDozeServiceHost != null) {
-            mDozeServiceHost.fireNotificationLight(false);
-        }
-    }
-
-    @Override
-    public void notificationLightPulse(int argb, int onMillis, int offMillis) {
-        if (mDozeServiceHost != null) {
-            mDozeServiceHost.fireNotificationLight(true);
-        }
-    }
-
-    @Override // CommandQueue
     public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
             int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
         final int oldVal = mSystemUiVisibility;
@@ -5059,44 +5038,9 @@
         return mStatusBarKeyguardViewManager.isShowing();
     }
 
-    private final class ShadeUpdates {
-        private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
-        private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
-
-        public void check() {
-            mNewVisibleNotifications.clear();
-            ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
-            for (int i = 0; i < activeNotifications.size(); i++) {
-                final Entry entry = activeNotifications.get(i);
-                final boolean visible = entry.row != null
-                        && entry.row.getVisibility() == View.VISIBLE;
-                if (visible) {
-                    mNewVisibleNotifications.add(entry.key + entry.notification.getPostTime());
-                }
-            }
-            final boolean updates = !mVisibleNotifications.containsAll(mNewVisibleNotifications);
-            mVisibleNotifications.clear();
-            mVisibleNotifications.addAll(mNewVisibleNotifications);
-
-            // We have new notifications
-            if (updates && mDozeServiceHost != null) {
-                mDozeServiceHost.fireNewNotifications();
-            }
-        }
-    }
-
     private final class DozeServiceHost implements DozeHost {
-        // Amount of time to allow to update the time shown on the screen before releasing
-        // the wakelock.  This timeout is design to compensate for the fact that we don't
-        // currently have a way to know when time display contents have actually been
-        // refreshed once we've finished rendering a new frame.
-        private static final long PROCESSING_TIME = 500;
-
         private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
 
-        // Keeps the last reported state by fireNotificationLight.
-        private boolean mNotificationLightOn;
-
         @Override
         public String toString() {
             return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
@@ -5114,19 +5058,6 @@
             }
         }
 
-        public void fireNotificationLight(boolean on) {
-            mNotificationLightOn = on;
-            for (Callback callback : mCallbacks) {
-                callback.onNotificationLight(on);
-            }
-        }
-
-        public void fireNewNotifications() {
-            for (Callback callback : mCallbacks) {
-                callback.onNewNotifications();
-            }
-        }
-
         @Override
         public void addCallback(@NonNull Callback callback) {
             mCallbacks.add(callback);
@@ -5192,11 +5123,6 @@
         }
 
         @Override
-        public boolean isNotificationLightOn() {
-            return mNotificationLightOn;
-        }
-
-        @Override
         public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
             StatusBar.this.startPendingIntentDismissingKeyguard(intent);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 6006d5a..11927729 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2766,6 +2766,7 @@
 
     private void updateNotificationAnimationStates() {
         boolean running = mAnimationsEnabled || mPulsing;
+        mShelf.setAnimationsEnabled(running);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index ab562d1..5d11ef3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -42,104 +42,11 @@
     private IStatusBarService mBarService;
 
     @Override
-    public void setIcon(String slot, StatusBarIcon icon) {
-    }
-
-    @Override
-    public void removeIcon(String slot) {
-    }
-
-    public void removeNotification(String key, RankingMap ranking) {
-    }
-
-    @Override
-    public void disable(int state1, int state2, boolean animate) {
-    }
-
-    @Override
-    public void animateExpandNotificationsPanel() {
-    }
-
-    @Override
-    public void animateCollapsePanels(int flags) {
-    }
-
-    @Override
-    public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
-            int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
-    }
-
-    @Override
-    public void topAppWindowChanged(boolean visible) {
-    }
-
-    @Override
-    public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
-            boolean showImeSwitcher) {
-    }
-
-    @Override // CommandQueue
-    public void setWindowState(int window, int state) {
-    }
-
-    @Override // CommandQueue
-    public void buzzBeepBlinked() {
-    }
-
-    @Override // CommandQueue
-    public void notificationLightOff() {
-    }
-
-    @Override // CommandQueue
-    public void notificationLightPulse(int argb, int onMillis, int offMillis) {
-    }
-
-    @Override
-    public void animateExpandSettingsPanel(String subPanel) {
-    }
-
-    @Override
-    public void showScreenPinningRequest(int taskId) {
-    }
-
-    @Override
-    public void appTransitionPending() {
-    }
-
-    @Override
-    public void appTransitionCancelled() {
-    }
-
-    @Override
-    public void appTransitionStarting(long startTime, long duration) {
-    }
-
-    @Override
-    public void appTransitionFinished() {
-    }
-
-    @Override
-    public void onCameraLaunchGestureDetected(int source) {
-    }
-
-    @Override
     public void showTvPictureInPictureMenu() {
         PipManager.getInstance().showTvPictureInPictureMenu();
     }
 
     @Override
-    public void addQsTile(ComponentName tile) {
-    }
-
-    @Override
-    public void remQsTile(ComponentName tile) {
-    }
-
-    @Override
-    public void clickTile(ComponentName tile) {
-    }
-
-    @Override
     public void start() {
         putComponent(TvStatusBar.class, this);
         CommandQueue commandQueue = getComponent(CommandQueue.class);
@@ -160,8 +67,4 @@
         }
     }
 
-    @Override
-    public void handleSystemNavigationKey(int arg1) {
-        // Not implemented
-    }
 }
diff --git a/packages/SystemUI/tests/res/layout/custom_view_dark.xml b/packages/SystemUI/tests/res/layout/custom_view_dark.xml
new file mode 100644
index 0000000..9e460a5
--- /dev/null
+++ b/packages/SystemUI/tests/res/layout/custom_view_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#ff000000"
+    />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 29d5a36..f22c1af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -15,11 +15,6 @@
 package com.android.systemui.qs;
 
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.support.test.runner.AndroidJUnit4;
 
 import com.android.systemui.Dependency;
 import com.android.systemui.FragmentTestCase;
@@ -27,28 +22,16 @@
 import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.tuner.TunerService;
-import com.android.systemui.utils.leaks.LeakCheckedTest;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.ArrayList;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.test.runner.AndroidJUnit4;
 
 @RunWith(AndroidJUnit4.class)
 public class QSFragmentTest extends FragmentTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 5401c30..95190e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -161,4 +161,10 @@
         assertEquals(top1.getValue().intValue(), top2.getValue().intValue());
         assertEquals(bottom1.getValue().intValue(), bottom2.getValue().intValue());
     }
+
+    @Test
+    public void testEmptyHeight() {
+        mTileLayout.measure(mLayoutSizeForOneTile, mLayoutSizeForOneTile);
+        assertEquals(0, mTileLayout.getMeasuredHeight());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 43f8629..5b22986 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -171,27 +171,6 @@
     }
 
     @Test
-    public void testBuzzBeepBlink() {
-        mCommandQueue.buzzBeepBlinked();
-        waitForIdleSync();
-        verify(mCallbacks).buzzBeepBlinked();
-    }
-
-    @Test
-    public void testNotificationLightOff() {
-        mCommandQueue.notificationLightOff();
-        waitForIdleSync();
-        verify(mCallbacks).notificationLightOff();
-    }
-
-    @Test
-    public void testNotificationLightPulse() {
-        mCommandQueue.notificationLightPulse(1, 2, 3);
-        waitForIdleSync();
-        verify(mCallbacks).notificationLightPulse(eq(1), eq(2), eq(3));
-    }
-
-    @Test
     public void testScreenPinRequest() {
         mCommandQueue.showScreenPinningRequest(1);
         waitForIdleSync();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
new file mode 100644
index 0000000..d07cea1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
+import com.android.systemui.statusbar.notification.NotificationViewWrapper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationCustomViewWrapperTest {
+
+    private Context mContext;
+    private ExpandableNotificationRow mRow;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mRow = new ExpandableNotificationRow(mContext, null);
+    }
+
+    @Test
+    public void testBackgroundPersists() {
+        RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
+        View v = views.apply(mContext, null);
+        NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
+        wrap.notifyContentUpdated(null, false /* isLowPriority */);
+        Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+        views.reapply(mContext, v);
+        wrap.notifyContentUpdated(null, false /* isLowPriority */);
+        Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+    }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
index f553277..b841ce9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
@@ -25,6 +25,7 @@
     public FakeTunerService(Context context, LeakCheckedTest test) {
         super(context);
         mBaseLeakChecker = new BaseLeakChecker<>(test, "tunable");
+        destroy();
     }
 
     @Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a861522..aae5dd8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -70,6 +70,8 @@
 import android.os.UserManagerInternal;
 import android.provider.Settings;
 import android.hardware.fingerprint.IFingerprintService;
+import android.provider.SettingsStringUtil.ComponentNameSet;
+import android.provider.SettingsStringUtil.SettingStringHelper;
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.util.Slog;
@@ -98,9 +100,9 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.SomeArgs;
 import com.android.server.LocalServices;
-
 import com.android.server.policy.AccessibilityShortcutController;
 import com.android.server.statusbar.StatusBarManagerInternal;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.FileDescriptor;
@@ -445,7 +447,7 @@
                 }
                 return userState.getClientState();
             } else {
-                userState.mClients.register(client);
+                userState.mUserClients.register(client);
                 // If this client is not for the current user we do not
                 // return a state since it is not for the foreground user.
                 // We will send the state to the client on a user switch.
@@ -813,6 +815,42 @@
         }
     }
 
+    /**
+     * Invoked remotely over AIDL by SysUi when the accessibility button within the system's
+     * navigation area has been clicked.
+     */
+    @Override
+    public void notifyAccessibilityButtonClicked() {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller does not hold permission "
+                    + android.Manifest.permission.STATUS_BAR);
+        }
+        synchronized (mLock) {
+            notifyAccessibilityButtonClickedLocked();
+        }
+    }
+
+    /**
+     * Invoked remotely over AIDL by SysUi when the availability of the accessibility
+     * button within the system's navigation area has changed.
+     *
+     * @param available {@code true} if the accessibility button is available to the
+     *                  user, {@code false} otherwise
+     */
+    @Override
+    public void notifyAccessibilityButtonAvailabilityChanged(boolean available) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller does not hold permission "
+                    + android.Manifest.permission.STATUS_BAR);
+        }
+        synchronized (mLock) {
+            notifyAccessibilityButtonAvailabilityChangedLocked(available);
+        }
+    }
+
+
     boolean onGesture(int gestureId) {
         synchronized (mLock) {
             boolean handled = notifyGestureLocked(gestureId, false);
@@ -927,7 +965,7 @@
             oldUserState.onSwitchToAnotherUser();
 
             // Disable the local managers for the old user.
-            if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
+            if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) {
                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
                         oldUserState.mUserId, 0).sendToTarget();
             }
@@ -1044,6 +1082,28 @@
         }
     }
 
+    private void notifyAccessibilityButtonClickedLocked() {
+        final UserState state = getCurrentUserStateLocked();
+        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
+            final Service service = state.mBoundServices.get(i);
+            // TODO(b/34720082): Only notify a single user-defined service
+            if (service.mRequestAccessibilityButton) {
+                service.notifyAccessibilityButtonClickedLocked();
+            }
+        }
+    }
+
+    private void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
+        final UserState state = getCurrentUserStateLocked();
+        state.mIsAccessibilityButtonAvailable = available;
+        for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
+            final Service service = state.mBoundServices.get(i);
+            if (service.mRequestAccessibilityButton) {
+                service.notifyAccessibilityButtonAvailabilityChangedLocked(available);
+            }
+        }
+    }
+
     /**
      * Removes an AccessibilityInteractionConnection.
      *
@@ -1178,7 +1238,7 @@
                 service.onAdded();
                 userState.mBoundServices.add(service);
                 userState.mComponentNameToServiceMap.put(service.mComponentName, service);
-                scheduleNotifyClientsOfServicesStateChange();
+                scheduleNotifyClientsOfServicesStateChange(userState);
             }
         } catch (RemoteException re) {
             /* do nothing */
@@ -1200,7 +1260,7 @@
             Service boundService = userState.mBoundServices.get(i);
             userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService);
         }
-        scheduleNotifyClientsOfServicesStateChange();
+        scheduleNotifyClientsOfServicesStateChange(userState);
     }
 
     /**
@@ -1362,16 +1422,16 @@
         final int clientState = userState.getClientState();
         if (userState.mLastSentClientState != clientState
                 && (mGlobalClients.getRegisteredCallbackCount() > 0
-                        || userState.mClients.getRegisteredCallbackCount() > 0)) {
+                        || userState.mUserClients.getRegisteredCallbackCount() > 0)) {
             userState.mLastSentClientState = clientState;
             mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
                     clientState, userState.mUserId).sendToTarget();
         }
     }
 
-    private void scheduleNotifyClientsOfServicesStateChange() {
-        mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS)
-                .sendToTarget();
+    private void scheduleNotifyClientsOfServicesStateChange(UserState userState) {
+        mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS,
+                userState.mUserId).sendToTarget();
     }
 
     private void scheduleUpdateInputFilter(UserState userState) {
@@ -2013,10 +2073,12 @@
      * Enables accessibility service specified by {@param componentName} for the {@param userId}.
      */
     private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
-        SettingsStringHelper settingsHelper = new SettingsStringHelper(
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userId);
-        settingsHelper.addService(componentName);
-        settingsHelper.writeToSettings();
+        final SettingStringHelper setting =
+                new SettingStringHelper(
+                        mContext.getContentResolver(),
+                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                        userId);
+        setting.write(ComponentNameSet.add(setting.read(), componentName));
 
         UserState userState = getUserStateLocked(userId);
         if (userState.mEnabledServices.add(componentName)) {
@@ -2028,10 +2090,12 @@
      * Disables accessibility service specified by {@param componentName} for the {@param userId}.
      */
     private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
-        SettingsStringHelper settingsHelper = new SettingsStringHelper(
-                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, userId);
-        settingsHelper.deleteService(componentName);
-        settingsHelper.writeToSettings();
+        final SettingStringHelper setting =
+                new SettingStringHelper(
+                        mContext.getContentResolver(),
+                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                        userId);
+        setting.write(ComponentNameSet.remove(setting.read(), componentName));
 
         UserState userState = getUserStateLocked(userId);
         if (userState.mEnabledServices.remove(componentName)) {
@@ -2060,45 +2124,6 @@
         return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
     }
 
-    private class SettingsStringHelper {
-        private static final String SETTINGS_DELIMITER = ":";
-        private ContentResolver mContentResolver;
-        private final String mSettingsName;
-        private Set<String> mServices;
-        private final int mUserId;
-
-        public SettingsStringHelper(String name, int userId) {
-            mUserId = userId;
-            mSettingsName = name;
-            mContentResolver = mContext.getContentResolver();
-            String servicesString = Settings.Secure.getStringForUser(
-                    mContentResolver, mSettingsName, userId);
-            mServices = new HashSet();
-            if (!TextUtils.isEmpty(servicesString)) {
-                final TextUtils.SimpleStringSplitter colonSplitter =
-                        new TextUtils.SimpleStringSplitter(SETTINGS_DELIMITER.charAt(0));
-                colonSplitter.setString(servicesString);
-                while (colonSplitter.hasNext()) {
-                    final String serviceName = colonSplitter.next();
-                    mServices.add(serviceName);
-                }
-            }
-        }
-
-        public void addService(ComponentName component) {
-            mServices.add(component.flattenToString());
-        }
-
-        public void deleteService(ComponentName component) {
-            mServices.remove(component.flattenToString());
-        }
-
-        public void writeToSettings() {
-            Settings.Secure.putStringForUser(mContentResolver, mSettingsName,
-                    TextUtils.join(SETTINGS_DELIMITER, mServices), mUserId);
-        }
-    }
-
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
@@ -2225,12 +2250,12 @@
                     final int clientState = msg.arg1;
                     final int userId = msg.arg2;
                     sendStateToClients(clientState, mGlobalClients);
-                    sendStateToClientsForUser(clientState, userId);
+                    sendStateToClients(clientState, getUserClientsForId(userId));
                 } break;
 
                 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
                     final int userId = msg.arg1;
-                    sendStateToClientsForUser(0, userId);
+                    sendStateToClients(0, getUserClientsForId(userId));
                 } break;
 
                 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
@@ -2257,7 +2282,9 @@
                 } break;
 
                 case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: {
-                    notifyClientsOfServicesStateChange();
+                    final int userId = msg.arg1;
+                    notifyClientsOfServicesStateChange(mGlobalClients);
+                    notifyClientsOfServicesStateChange(getUserClientsForId(userId));
                 } break;
 
                 case MSG_UPDATE_FINGERPRINT: {
@@ -2282,12 +2309,12 @@
             }
         }
 
-        private void sendStateToClientsForUser(int clientState, int userId) {
+        private RemoteCallbackList<IAccessibilityManagerClient> getUserClientsForId(int userId) {
             final UserState userState;
             synchronized (mLock) {
                 userState = getUserStateLocked(userId);
             }
-            sendStateToClients(clientState, userState.mClients);
+            return userState.mUserClients;
         }
 
         private void sendStateToClients(int clientState,
@@ -2307,11 +2334,8 @@
             }
         }
 
-        private void notifyClientsOfServicesStateChange() {
-            RemoteCallbackList<IAccessibilityManagerClient> clients;
-            synchronized (mLock) {
-                clients = getCurrentUserStateLocked().mClients;
-            }
+        private void notifyClientsOfServicesStateChange(
+                RemoteCallbackList<IAccessibilityManagerClient> clients) {
             try {
                 final int userClientCount = clients.beginBroadcast();
                 for (int i = 0; i < userClientCount; i++) {
@@ -2426,6 +2450,8 @@
 
         boolean mCaptureFingerprintGestures;
 
+        boolean mRequestAccessibilityButton;
+
         int mFetchFlags;
 
         long mNotificationTimeout;
@@ -2581,6 +2607,8 @@
                     & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
             mCaptureFingerprintGestures = (info.flags
                     & AccessibilityServiceInfo.FLAG_CAPTURE_FINGERPRINT_GESTURES) != 0;
+            mRequestAccessibilityButton = (info.flags
+                    & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
         }
 
         /**
@@ -2694,7 +2722,7 @@
                     }
                     UserState userState = getUserStateLocked(mUserId);
                     onUserStateChangedLocked(userState);
-                    scheduleNotifyClientsOfServicesStateChange();
+                    scheduleNotifyClientsOfServicesStateChange(userState);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -2904,7 +2932,7 @@
         public boolean findAccessibilityNodeInfoByAccessibilityId(
                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int flags,
-                long interrogatingTid) throws RemoteException {
+                long interrogatingTid, Bundle arguments) throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             Region partialInteractiveRegion = Region.obtain();
@@ -2936,7 +2964,7 @@
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
                         partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
-                        interrogatingPid, interrogatingTid, spec);
+                        interrogatingPid, interrogatingTid, spec, arguments);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
@@ -3332,6 +3360,19 @@
         }
 
         @Override
+        public boolean isAccessibilityButtonAvailable() {
+            final UserState userState;
+            synchronized (mLock) {
+                if (!isCalledForCurrentUserLocked()) {
+                    return false;
+                }
+                userState = getCurrentUserStateLocked();
+            }
+
+            return mRequestAccessibilityButton && userState.mIsAccessibilityButtonAvailable;
+        }
+
+        @Override
         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
             synchronized (mLock) {
@@ -3544,6 +3585,14 @@
             mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
         }
 
+        public void notifyAccessibilityButtonClickedLocked() {
+            mInvocationHandler.notifyAccessibilityButtonClickedLocked();
+        }
+
+        public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
+            mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available);
+        }
+
         /**
          * Called by the invocation handler to notify the service that the
          * state of magnification has changed.
@@ -3582,6 +3631,36 @@
             }
         }
 
+        private void notifyAccessibilityButtonClickedInternal() {
+            final IAccessibilityServiceClient listener;
+            synchronized (mLock) {
+                listener = mServiceInterface;
+            }
+            if (listener != null) {
+                try {
+                    listener.onAccessibilityButtonClicked();
+                } catch (RemoteException re) {
+                    Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re);
+                }
+            }
+        }
+
+        private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) {
+            final IAccessibilityServiceClient listener;
+            synchronized (mLock) {
+                listener = mServiceInterface;
+            }
+            if (listener != null) {
+                try {
+                    listener.onAccessibilityButtonAvailabilityChanged(available);
+                } catch (RemoteException re) {
+                    Slog.e(LOG_TAG,
+                            "Error sending accessibility button availability change to " + mService,
+                            re);
+                }
+            }
+        }
+
         private void notifyGestureInternal(int gestureId) {
             final IAccessibilityServiceClient listener;
             synchronized (mLock) {
@@ -3723,6 +3802,8 @@
 
             private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
             private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
+            private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7;
+            private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8;
 
             private boolean mIsMagnificationCallbackEnabled = false;
             private boolean mIsSoftKeyboardCallbackEnabled = false;
@@ -3758,6 +3839,15 @@
                         notifySoftKeyboardShowModeChangedInternal(showState);
                     } break;
 
+                    case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: {
+                        notifyAccessibilityButtonClickedInternal();
+                    } break;
+
+                    case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
+                        final boolean available = (message.arg1 != 0);
+                        notifyAccessibilityButtonAvailabilityChangedInternal(available);
+                    } break;
+
                     default: {
                         throw new IllegalArgumentException("Unknown message: " + type);
                     }
@@ -3797,6 +3887,17 @@
             public void setSoftKeyboardCallbackEnabled(boolean enabled) {
                 mIsSoftKeyboardCallbackEnabled = enabled;
             }
+
+            public void notifyAccessibilityButtonClickedLocked() {
+                final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED);
+                msg.sendToTarget();
+            }
+
+            public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
+                final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED,
+                        (available ? 1 : 0), 0);
+                msg.sendToTarget();
+            }
         }
     }
 
@@ -4467,7 +4568,7 @@
 
         // Non-transient state.
 
-        public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
+        public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
             new RemoteCallbackList<>();
 
         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
@@ -4501,6 +4602,8 @@
 
         public int mSoftKeyboardShowMode = 0;
 
+        public boolean mIsAccessibilityButtonAvailable;
+
         public boolean mIsTouchExplorationEnabled;
         public boolean mIsTextHighContrastEnabled;
         public boolean mIsEnhancedWebAccessibilityEnabled;
@@ -4575,6 +4678,9 @@
             mIsDisplayMagnificationEnabled = false;
             mIsAutoclickEnabled = false;
             mSoftKeyboardShowMode = 0;
+
+            // Clear state tracked from system UI
+            mIsAccessibilityButtonAvailable = false;
         }
 
         public void destroyUiAutomationService() {
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 78436f7..9347350 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -18,8 +18,11 @@
 
 import static android.Manifest.permission.MANAGE_AUTO_FILL;
 import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
+import static com.android.server.autofill.Helper.DEBUG;
+import static com.android.server.autofill.Helper.VERBOSE;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.content.ComponentName;
@@ -34,8 +37,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
@@ -43,7 +44,6 @@
 import android.provider.Settings;
 import android.service.autofill.IAutoFillManagerService;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Slog;
@@ -72,66 +72,47 @@
 public final class AutoFillManagerService extends SystemService {
 
     private static final String TAG = "AutoFillManagerService";
-    static final boolean DEBUG = true; // TODO(b/33197203): change to false once stable
 
-    private static final long SERVICE_BINDING_LIFETIME_MS = 5 * DateUtils.MINUTE_IN_MILLIS;
+    private static final int MSG_START_SESSION = 1;
+    private static final int MSG_UPDATE_SESSION = 2;
+    private static final int MSG_FINISH_SESSION = 3;
+    private static final int MSG_REQUEST_SAVE_FOR_USER = 4;
 
-    private static final int MSG_UNBIND = 1;
-    private static final int MSG_REQUEST_AUTO_FILL_FOR_USER = 2;
-    private static final int MSG_REQUEST_AUTO_FILL = 3;
-    private static final int MSG_ON_VALUE_CHANGED = 4;
-    private static final int MSG_REQUEST_SAVE_FOR_USER = 5;
-
-    private final AutoFillManagerServiceStub mServiceStub;
     private final Context mContext;
-    private final ContentResolver mResolver;
+    private final AutoFillUI mUi;
 
     private final Object mLock = new Object();
 
-    private final HandlerCaller.Callback mHandlerCallback = new HandlerCaller.Callback() {
-
-        @Override
-        public void executeMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_UNBIND: {
-                    synchronized (mLock) {
-                        removeCachedServiceLocked(msg.arg1);
-                    }
-                    return;
-                } case MSG_REQUEST_AUTO_FILL_FOR_USER: {
-                    handleAutoFillForUser(msg.arg1);
-                    return;
-                } case MSG_REQUEST_SAVE_FOR_USER: {
-                    handleSaveForUser(msg.arg1);
-                    return;
-                } case MSG_REQUEST_AUTO_FILL: {
-                    final SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        final int userId = msg.arg1;
-                        final int flags = msg.arg2;
-                        final IBinder activityToken = (IBinder) args.arg1;
-                        final AutoFillId autoFillId = (AutoFillId) args.arg2;
-                        final Rect bounds = (Rect) args.arg3;
-                        handleAutoFill(activityToken, userId, autoFillId, bounds, flags);
-                    } finally {
-                        args.recycle();
-                    }
-                    return;
-                } case MSG_ON_VALUE_CHANGED: {
-                    final SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        final int userId = msg.arg1;
-                        final IBinder activityToken = (IBinder) args.arg1;
-                        final AutoFillId autoFillId = (AutoFillId) args.arg2;
-                        final AutoFillValue newValue = (AutoFillValue) args.arg3;
-                        handleValueChanged(activityToken, userId, autoFillId, newValue);
-                    } finally {
-                        args.recycle();
-                    }
-                    return;
-                } default: {
-                    Slog.w(TAG, "Invalid message: " + msg);
-                }
+    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+        switch (msg.what) {
+            case MSG_START_SESSION: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                final int userId = msg.arg1;
+                final IBinder activityToken = (IBinder) args.arg1;
+                final IBinder appCallback = (IBinder) args.arg2;
+                final AutoFillId autoFillId = (AutoFillId) args.arg3;
+                final Rect bounds = (Rect) args.arg4;
+                final AutoFillValue value = (AutoFillValue) args.arg5;
+                handleStartSession(userId, activityToken, appCallback, autoFillId, bounds, value);
+                return;
+            } case MSG_FINISH_SESSION: {
+                handleFinishSession(msg.arg1, (IBinder) msg.obj);
+                return;
+            } case MSG_REQUEST_SAVE_FOR_USER: {
+                handleSaveForUser(msg.arg1);
+                return;
+            } case MSG_UPDATE_SESSION: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                final IBinder activityToken = (IBinder) args.arg1;
+                final AutoFillId autoFillId = (AutoFillId) args.arg2;
+                final Rect bounds = (Rect) args.arg3;
+                final AutoFillValue value = (AutoFillValue) args.arg4;
+                final int userId = args.argi5;
+                final int flags = args.argi6;
+                handleUpdateSession(userId, activityToken, autoFillId, bounds, value, flags);
+                return;
+            } default: {
+                Slog.w(TAG, "Invalid message: " + msg);
             }
         }
     };
@@ -148,10 +129,10 @@
      * Entries on this cache are added on demand and removed when:
      * <ol>
      *   <li>An auto-fill service app is removed.
-     *   <li>The {@link android.provider.Settings.Secure#AUTO_FILL_SERVICE} for an user change.
-     *   <li>It has not been interacted with for {@link #SERVICE_BINDING_LIFETIME_MS} ms.
+     *   <li>The {@link android.provider.Settings.Secure#AUTO_FILL_SERVICE} for an user change.\
      * </ol>
      */
+    // TODO(b/33197203): Update the above comment
     @GuardedBy("mLock")
     private SparseArray<AutoFillManagerServiceImpl> mServicesCache = new SparseArray<>();
 
@@ -160,19 +141,14 @@
 
     public AutoFillManagerService(Context context) {
         super(context);
-
         mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
-
         mContext = context;
-
-        mResolver = context.getContentResolver();
-        mServiceStub = new AutoFillManagerServiceStub();
+        mUi = new AutoFillUI(mContext);
     }
 
     @Override
     public void onStart() {
-        if (DEBUG) Slog.d(TAG, "onStart(): binding as " + AUTO_FILL_MANAGER_SERVICE);
-        publishBinderService(AUTO_FILL_MANAGER_SERVICE, mServiceStub);
+        publishBinderService(AUTO_FILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
     }
 
     @Override
@@ -186,61 +162,44 @@
         ComponentName serviceComponent = null;
         ServiceInfo serviceInfo = null;
         final String componentName = Settings.Secure.getStringForUser(
-                mResolver, Settings.Secure.AUTO_FILL_SERVICE, userId);
+                mContext.getContentResolver(), 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);
+                Slog.e(TAG, "Bad auto-fill service name " + componentName, e);
                 return null;
             }
         }
 
-        if (DEBUG) {
-            Slog.d(TAG, "getServiceComponentForUser(" + userId + "): component="
-                    + serviceComponent + ", info: " + serviceInfo);
-        }
         if (serviceInfo == null) {
-            if (DEBUG) Slog.d(TAG, "no service info for " + serviceComponent);
             return null;
         }
-        return new AutoFillManagerServiceImpl(this, mContext, mLock, mRequestsHistory,
-                userId, serviceInfo.applicationInfo.uid, serviceComponent,
-                SERVICE_BINDING_LIFETIME_MS);
+
+        try {
+            return new AutoFillManagerServiceImpl(mContext, mLock, mRequestsHistory,
+                    userId, serviceComponent, mUi);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.w(TAG, "Auto-fill service not found: " + serviceComponent, e);
+        }
+
+        return null;
     }
 
     /**
      * Gets the service instance for an user.
-     * <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.
+     *
+     * @return service instance or {@code null} if user does not have a service set.
      */
-    // TODO(b/33197203): make private once AutoFillUi does not uses notifications
+    @Nullable
     AutoFillManagerServiceImpl getServiceForUserLocked(int userId) {
         AutoFillManagerServiceImpl service = mServicesCache.get(userId);
-        if (service != null) {
-            if (DEBUG)
-                Log.d(TAG, "reusing cached service for userId " + userId);
-            service.setLifeExpectancy(SERVICE_BINDING_LIFETIME_MS);
-        } else {
+        if (service == null) {
             service = newServiceForUser(userId);
-            if (service == null) {
-                // Already logged
-                return null;
-            }
-            if (DEBUG) Log.d(TAG, "creating new cached service for userId " + userId);
-            service.startLocked();
             mServicesCache.put(userId, service);
         }
-        // Keep service connection alive for a while, in case user needs to interact with it
-        // (for example, to save the data that was inputted in)
-        if (mHandlerCaller.hasMessages(MSG_UNBIND)) {
-            mHandlerCaller.removeMessages(MSG_UNBIND);
-        }
-        mHandlerCaller.sendMessageDelayed(mHandlerCaller.obtainMessageI(MSG_UNBIND, userId),
-                SERVICE_BINDING_LIFETIME_MS);
         return service;
     }
 
@@ -248,35 +207,43 @@
      * Removes a cached service for a given user.
      */
     void removeCachedServiceLocked(int userId) {
-        if (DEBUG) Log.d(TAG, "removing cached service for userId " + userId);
         final AutoFillManagerServiceImpl service = mServicesCache.get(userId);
-        if (service == null) {
-            if (DEBUG) {
-                Log.d(TAG, "removeCachedServiceForUser(): no cached service for userId " + userId);
-            }
-            return;
-        }
-        mServicesCache.delete(userId);
-        service.stopLocked();
-    }
-
-    private void handleAutoFill(IBinder activityToken, int userId, AutoFillId autoFillId,
-            Rect bounds, int flags) {
-        synchronized (mLock) {
-            final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-            if (service != null) {
-                service.requestAutoFillLocked(activityToken, autoFillId, bounds, flags);
-            }
+        if (service != null) {
+            mServicesCache.delete(userId);
+            service.destroyLocked();
         }
     }
 
-    private void handleValueChanged(IBinder activityToken, int userId, AutoFillId autoFillId,
-            AutoFillValue newValue) {
+    private void handleStartSession(int userId, IBinder activityToken, IBinder appCallback,
+            AutoFillId autoFillId, Rect bounds, AutoFillValue value) {
         synchronized (mLock) {
             final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-            if (service != null) {
-                service.onValueChangeLocked(activityToken, autoFillId, newValue);
+            if (service == null) {
+                return;
             }
+           service.startSessionLocked(activityToken, appCallback, autoFillId, bounds, value);
+        }
+    }
+
+    private void handleFinishSession(int userId, IBinder activityToken) {
+        synchronized (mLock) {
+            final AutoFillManagerServiceImpl service = mServicesCache.get(userId);
+            if (service == null) {
+                return;
+            }
+            service.finishSessionLocked(activityToken);
+        }
+    }
+
+    private void handleUpdateSession(int userId, IBinder activityToken, AutoFillId autoFillId,
+            Rect bounds, AutoFillValue value, int flags) {
+        synchronized (mLock) {
+            final AutoFillManagerServiceImpl service = mServicesCache.get(userId);
+            if (service == null) {
+                return;
+            }
+
+            service.updateSessionLocked(activityToken, autoFillId, bounds, value, flags);
         }
     }
 
@@ -291,98 +258,70 @@
         return topActivities.get(0);
     }
 
-    private void handleAutoFillForUser(int userId) {
-        if (DEBUG) Slog.d(TAG, "handler.requestAutoFillForUser(): id=" + userId);
-        final IBinder activityToken = getTopActivityForUser();
-        if (activityToken == null) {
-            return;
-        }
-
-        synchronized (mLock) {
-            final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-            if (service == null) {
-                Slog.w(TAG, "no service for user " + userId);
-                return;
-            }
-            service.requestAutoFillLocked(activityToken, null, null, 0);
-        }
-    }
-
     private void handleSaveForUser(int userId) {
-        if (DEBUG) Slog.d(TAG, "handler.handleSaveForUser(): id=" + userId);
         final IBinder activityToken = getTopActivityForUser();
-        if (activityToken == null) {
-            return;
-        }
+        if (activityToken != null) {
+            synchronized (mLock) {
+                final AutoFillManagerServiceImpl service = mServicesCache.get(userId);
+                if (service == null) {
+                    Log.w(TAG, "handleSaveForUser(): no cached service for userId " + userId);
+                    return;
+                }
 
-        synchronized (mLock) {
-            final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-            if (service == null) {
-                Slog.w(TAG, "no service for user " + userId);
-                return;
+                service.requestSaveForUserLocked(activityToken);
             }
-            service.requestSaveForUserLocked(activityToken);
         }
     }
 
-    private IBinder getTopActivity() {
-        final int uid = Binder.getCallingUid();
-        final IBinder activityToken = LocalServices.getService(ActivityManagerInternal.class)
-                .getTopVisibleActivity(uid);
-        if (activityToken == null) {
-            // Make sure its called by the top activity.
-            if (uid == Process.SYSTEM_UID) {
-                // TODO(b/33197203, b/34819567, b/34171325): figure out proper way to handle it
-                if (DEBUG) Log.w(TAG, "requestAutoFill(): ignoring call from system");
-
-                return null;
-            }
-            throw new SecurityException("uid " + uid + " does not own the top activity");
-        }
-
-        return activityToken;
-    }
-
     final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
 
         @Override
-        public void requestAutoFill(AutoFillId id, Rect bounds, int flags) {
-            if (DEBUG) Slog.d(TAG, "requestAutoFill: flags=" + flags + ", autoFillId=" + id
-                    + ", bounds=" + bounds);
+        public void startSession(IBinder activityToken, IBinder appCallback, AutoFillId autoFillId,
+                Rect bounds, AutoFillValue value) throws RemoteException {
+            // TODO(b/33197203): make sure it's called by resumed / focused activity
 
-            final IBinder activityToken = getTopActivity();
-            if (activityToken != null) {
-                mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIIOOO(MSG_REQUEST_AUTO_FILL,
-                        UserHandle.getCallingUserId(), flags, activityToken, id, bounds));
+            final int userId = UserHandle.getCallingUserId();
+            if (VERBOSE) {
+                Slog.v(TAG, "startSession: autoFillId=" + autoFillId + ", bounds=" + bounds
+                        + ", value=" + value);
             }
+
+            final SomeArgs args = SomeArgs.obtain();
+            args.arg1 = activityToken;
+            args.arg2 = appCallback;
+            args.arg3 = autoFillId;
+            args.arg4 = bounds;
+            args.arg5 = value;
+
+            mHandlerCaller.sendMessage(mHandlerCaller.getHandler().obtainMessage(MSG_START_SESSION,
+                    userId, 0, args));
         }
 
         @Override
-        public void requestAutoFillForUser(int userId) {
-            mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+        public void updateSession(IBinder activityToken, AutoFillId id, Rect bounds,
+                AutoFillValue value, int flags) throws RemoteException {
+            if (DEBUG) {
+                Slog.d(TAG, "updateSession: flags=" + flags + ", autoFillId=" + id
+                        + ", bounds=" + bounds + ", value=" + value);
+            }
 
-            mHandlerCaller.sendMessage(
-                    mHandlerCaller.obtainMessageI(MSG_REQUEST_AUTO_FILL_FOR_USER, userId));
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOOII(MSG_UPDATE_SESSION,
+                    activityToken, id, bounds, value, UserHandle.getCallingUserId(), flags));
+        }
+
+        @Override
+        public void finishSession(IBinder activityToken) throws RemoteException {
+            if (VERBOSE) Slog.v(TAG, "finishSession(): " + activityToken);
+
+            mHandlerCaller.sendMessage(mHandlerCaller.getHandler().obtainMessage(MSG_FINISH_SESSION,
+                    UserHandle.getCallingUserId(), 0, activityToken));
         }
 
         @Override
         public void requestSaveForUser(int userId) {
             mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
-
-            mHandlerCaller.sendMessage(
-                    mHandlerCaller.obtainMessageI(MSG_REQUEST_SAVE_FOR_USER, userId));
-        }
-
-        @Override
-        public void onValueChanged(AutoFillId id, AutoFillValue value) {
-            if (DEBUG) Slog.d(TAG, "onValueChanged(): id=" + id + ", value=" + value);
-
-            final IBinder activityToken = getTopActivity();
-
-            if (activityToken != null) {
-                mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOOO(MSG_ON_VALUE_CHANGED,
-                        UserHandle.getCallingUserId(), activityToken, id, value));
-            }
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageI(MSG_REQUEST_SAVE_FOR_USER,
+                    userId));
         }
 
         @Override
@@ -407,6 +346,7 @@
                         impl.dumpLocked("  ", pw);
                     }
                 }
+                mUi.dump(pw);
             }
             pw.println("Requests history:");
             mRequestsHistory.reverseDump(fd, pw, args);
@@ -430,7 +370,6 @@
 
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
-            if (DEBUG) Slog.d(TAG, "settings (" + uri + " changed for " + userId);
             synchronized (mLock) {
                 removeCachedServiceLocked(userId);
             }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 42e4fd3..88f1bda 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -16,15 +16,17 @@
 
 package com.android.server.autofill;
 
-import static android.service.autofill.AutoFillService.FLAG_AUTHENTICATION_ERROR;
-import static android.service.autofill.AutoFillService.FLAG_AUTHENTICATION_REQUESTED;
-import static android.service.autofill.AutoFillService.FLAG_AUTHENTICATION_SUCCESS;
-import static android.view.autofill.AutoFillManager.FLAG_UPDATE_UI_SHOW;
-import static android.view.autofill.AutoFillManager.FLAG_UPDATE_UI_HIDE;
+import static android.service.autofill.AutoFillService.EXTRA_ACTIVITY_TOKEN;
+import static android.service.voice.VoiceInteractionSession.KEY_RECEIVER_EXTRAS;
+import static android.service.voice.VoiceInteractionSession.KEY_STRUCTURE;
+import static android.view.autofill.AutoFillManager.FLAG_FOCUS_GAINED;
+import static android.view.autofill.AutoFillManager.FLAG_FOCUS_LOST;
+import static android.view.autofill.AutoFillManager.FLAG_START_SESSION;
+import static android.view.autofill.AutoFillManager.FLAG_VALUE_CHANGED;
 
 import static com.android.server.autofill.Helper.DEBUG;
 import static com.android.server.autofill.Helper.VERBOSE;
-import static com.android.server.autofill.Helper.bundleToString;
+import static com.android.server.autofill.Helper.findValue;
 
 import android.annotation.Nullable;
 import android.app.Activity;
@@ -38,47 +40,36 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
+import android.content.IntentSender;
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.IFingerprintService;
-import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.os.Binder;
 import android.os.Bundle;
-import android.os.DeadObjectException;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
+import android.os.Looper;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
 import android.service.autofill.AutoFillService;
 import android.service.autofill.AutoFillServiceInfo;
+import android.service.autofill.FillCallback;
 import android.service.autofill.IAutoFillAppCallback;
-import android.service.autofill.IAutoFillServerCallback;
 import android.service.autofill.IAutoFillService;
-import android.service.voice.VoiceInteractionSession;
+import android.service.autofill.IFillCallback;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.LocalLog;
-import android.util.Log;
 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.AutoFillValue;
 import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.IResultReceiver;
 import com.android.server.FgThread;
 
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -91,28 +82,16 @@
 
     private static final String TAG = "AutoFillManagerServiceImpl";
 
-    /** Used do assign ids to new ServerCallback instances. */
-    private static int sSessionIdCounter = 0;
+    private static final int MSG_SERVICE_SAVE = 1;
 
     private final int mUserId;
-    private final int mUid;
     private final ComponentName mComponent;
     private final String mComponentName;
     private final Context mContext;
     private final IActivityManager mAm;
     private final Object mLock;
     private final AutoFillServiceInfo mInfo;
-    private final AutoFillManagerService mManagerService;
-
-    // Token used for fingerprint authentication
-    // TODO(b/33197203): create on demand?
-    private final IBinder mAuthToken = new Binder();
-
-    private final IFingerprintService mFingerprintService =
-            IFingerprintService.Stub.asInterface(ServiceManager.getService("fingerprint"));
-
-    @GuardedBy("mLock")
-    private final List<QueuedRequest> mQueuedRequests = new LinkedList<>();
+    private final AutoFillUI mUi;
 
     private final LocalLog mRequestsHistory;
 
@@ -122,21 +101,25 @@
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                 final String reason = intent.getStringExtra("reason");
                 if (DEBUG) Slog.d(TAG, "close system dialogs: " + reason);
-
-                synchronized (mLock) {
-                    final int size = mSessions.size();
-                    for (int i = 0; i < size; i++) {
-                        final Session session = mSessions.valueAt(i);
-                        // TODO(b/33197203): invalidate the sessions instead?
-                        session.mUi.closeAll();
-                    }
-                }
+                mUi.hideAll();
             }
         }
     };
 
+    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+        switch (msg.what) {
+            case MSG_SERVICE_SAVE:
+                handleSessionSave((IBinder) msg.obj);
+                break;
+            default:
+                Slog.d(TAG, "invalid msg: " + msg);
+        }
+    };
+
+    private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(),
+            mHandlerCallback, true);
     /**
-     * Cache of pending {@link Session}s, keyed by {@link Session#mId}.
+     * Cache of pending {@link Session}s, keyed by {@code activityToken}.
      *
      * <p>They're kept until the {@link AutoFillService} finished handling a request, an error
      * occurs, or the session times out.
@@ -144,237 +127,116 @@
     // TODO(b/33197203): need to make sure service is bound while callback is pending and/or
     // use WeakReference
     @GuardedBy("mLock")
-    private static final SparseArray<Session> mSessions = new SparseArray<>();
-
-    private final ServiceConnection mConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            if (DEBUG) Slog.d(TAG, "onServiceConnected():" + name);
-            synchronized (mLock) {
-                mService = IAutoFillService.Stub.asInterface(service);
-                try {
-                    mService.onConnected();
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception on service.onConnected(): " + e);
-                    return;
-                }
-                if (!mQueuedRequests.isEmpty()) {
-                    if (DEBUG) Slog.d(TAG, "queued requests:" + mQueuedRequests.size());
-                }
-                for (final QueuedRequest request: mQueuedRequests) {
-                    requestAutoFillLocked(request.activityToken, request.autoFillId,
-                            request.bounds, request.flags, false);
-                }
-                mQueuedRequests.clear();
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            if (DEBUG) Slog.d(TAG, name + " disconnected");
-            synchronized (mLock) {
-                mService = null;
-                mManagerService.removeCachedServiceLocked(mUserId);
-            }
-        }
-    };
+    private final ArrayMap<IBinder, Session> mSessions = new ArrayMap<>();
 
     /**
-     * Receiver of assist data from the app's {@link Activity}, uses the {@code resultData} as
-     * the {@link Session#mId}.
+     * Receiver of assist data from the app's {@link Activity}.
      */
     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");
+            final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
+
+            if (structure == null) {
+                Slog.w(TAG, "no assist structure for id " + resultCode);
                 return;
             }
-            final AssistStructure structure = resultData
-                    .getParcelable(VoiceInteractionSession.KEY_STRUCTURE);
 
+            final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS);
+            if (receiverExtras == null) {
+                // Should not happen
+                Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver");
+                return;
+            }
+
+            final IBinder activityToken = receiverExtras.getBinder(EXTRA_ACTIVITY_TOKEN);
             final Session session;
             synchronized (mLock) {
-                session = mSessions.get(resultCode);
+                session = mSessions.get(activityToken);
                 if (session == null) {
-                    Slog.w(TAG, "no server callback for id " + resultCode);
+                    Slog.w(TAG, "no server session for activityToken " + activityToken);
                     return;
                 }
-                session.setAppCallbackLocked(appBinder);
                 // TODO(b/33197203): since service is fetching the data (to use for save later),
                 // we should optimize what's sent (for example, remove layout containers,
                 // color / font info, etc...)
                 session.mStructure = structure;
-
-                // TODO(b/33197203, b/33269702): Must fetch the data so it's available later on
-                // handleSave(), even if if the activity is gone by then, but structure.ensureData()
-                // gives a ONE_WAY warning because system_service could block on app calls.
-                // We need to change AssistStructure so it provides a "one-way" writeToParcel()
-                // method that sends all the data
-                structure.ensureData();
-
-                structure.sanitizeForParceling(true);
-                if (VERBOSE) {
-                    Slog.v(TAG, "Dumping " + structure + " before calling service.autoFill()");
-                    structure.dump();
-                }
-                mService.autoFill(structure, session.mServerCallback);
             }
+
+            // TODO(b/33197203): Need to pipe the bundle
+            session.mRemoteFillService.onFillRequest(structure, null);
         }
     };
 
-    @GuardedBy("mLock")
-    private IAutoFillService mService;
-    @GuardedBy("mLock")
-    private boolean mBound;
-    @GuardedBy("mLock")
-    private boolean mValid;
-
-    // Estimated time when the service will be evicted from the cache.
-    long mEstimateTimeOfDeath;
-
-    AutoFillManagerServiceImpl(AutoFillManagerService managerService, Context context, Object lock,
-            LocalLog requestsHistory, int userId, int uid, ComponentName component, long ttl) {
-        mManagerService = managerService;
+    AutoFillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory,
+            int userId, ComponentName component, AutoFillUI ui)
+            throws PackageManager.NameNotFoundException {
         mContext = context;
         mLock = lock;
         mRequestsHistory = requestsHistory;
         mUserId = userId;
-        mUid = uid;
         mComponent = component;
         mComponentName = mComponent.flattenToShortString();
         mAm = ActivityManager.getService();
-        setLifeExpectancy(ttl);
+        mUi = ui;
+        mInfo = new AutoFillServiceInfo(context.getPackageManager(), component, mUserId);
 
-        final AutoFillServiceInfo info;
-        try {
-            info = new AutoFillServiceInfo(context.getPackageManager(), component, mUserId);
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "Auto-fill service not found: " + component, e);
-            mInfo = null;
-            mValid = false;
-            return;
-        }
-        mInfo = info;
-        if (mInfo.getParseError() != null) {
-            Slog.w(TAG, "Bad auto-fill service: " + mInfo.getParseError());
-            mValid = false;
-            return;
-        }
-
-        mValid = true;
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         mContext.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
     }
 
-    void setLifeExpectancy(long ttl) {
-        mEstimateTimeOfDeath = SystemClock.uptimeMillis() + ttl;
-    }
-
-    void startLocked() {
-        if (DEBUG) Slog.d(TAG, "startLocked()");
-
-        final Intent intent = new Intent(AutoFillService.SERVICE_INTERFACE);
-        intent.setComponent(mComponent);
-        mBound = mContext.bindServiceAsUser(intent, mConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUserId));
-
-        if (!mBound) {
-            Slog.w(TAG, "Failed binding to auto-fill service " + mComponent);
-            return;
-        }
-        if (DEBUG) Slog.d(TAG, "Bound to " + mComponent);
-    }
-
-    /**
-     * Asks service to auto-fill an activity.
-     *
-     * @param activityToken activity token.
-     * @param autoFillId id of the view that requested auto-fill.
-     * @param bounds boundaries of the view that requested auto-fill.
-     * @param flags optional flags.
-     */
-    void requestAutoFillLocked(IBinder activityToken, @Nullable AutoFillId autoFillId,
-            @Nullable Rect bounds, int flags) {
-        if (!mBound) {
-            Slog.w(TAG, "requestAutoFillLocked() failed because it's not bound to service");
-            return;
-        }
-
-        requestAutoFillLocked(activityToken, autoFillId, bounds, flags, true);
-    }
 
     /**
      * Used by {@link AutoFillManagerServiceShellCommand} to request save for the current top app.
      */
     void requestSaveForUserLocked(IBinder activityToken) {
-        if (!mBound) {
-            Slog.w(TAG, "requestSaveForUserLocked() failed because it's not bound to service");
-            return;
-        }
-        if (mService == null) {
-            Slog.w(TAG, "requestSaveForUserLocked: service not set");
-            return;
-        }
-
-        final Session session = getSessionByTokenLocked(activityToken);
+        final Session session = mSessions.get(activityToken);
         if (session == null) {
             Slog.w(TAG, "requestSaveForUserLocked(): no session for " + activityToken);
             return;
         }
 
-        session.onSaveLocked();
+        session.callSaveLocked();
     }
 
-    private void requestAutoFillLocked(IBinder activityToken, @Nullable AutoFillId autoFillId,
-            @Nullable Rect bounds, int flags, boolean queueIfNecessary) {
-        if (mService == null) {
-            if (!queueIfNecessary) {
-                Slog.w(TAG, "requestAutoFillLocked(): service is null");
-                return;
-            }
-            if (DEBUG) Slog.d(TAG, "requestAutoFillLocked(): service not set yet, queuing it");
-            mQueuedRequests.add(new QueuedRequest(activityToken, autoFillId, bounds, flags));
-            return;
-        }
-
-        final String historyItem = "s=" + mComponentName + " u=" + mUserId + " f=" + flags
-                + " a=" + activityToken + " i=" + autoFillId + " b=" + bounds;
+    void startSessionLocked(IBinder activityToken, IBinder appCallbackToken, AutoFillId autoFillId,
+            Rect bounds, AutoFillValue value) {
+        final String historyItem = "s=" + mComponentName + " u=" + mUserId + " a=" + activityToken
+                + " i=" + autoFillId + " b=" + bounds + " v=" + value;
         mRequestsHistory.log(historyItem);
 
         // TODO(b/33197203): Handle partitioning
-        Session session = getSessionByTokenLocked(activityToken);
+        final Session session = mSessions.get(activityToken);
+        if (session != null) {
+            // Already started...
+            return;
+        }
+
+        final Session newSession = createSessionByTokenLocked(activityToken, appCallbackToken);
+        newSession.updateLocked(autoFillId, bounds, value, FLAG_START_SESSION);
+        newSession.enableSessionLocked();
+    }
+
+    void finishSessionLocked(IBinder activityToken) {
+        if (DEBUG) Slog.d(TAG, "finishSessionLocked(): " + activityToken);
+        final Session session = mSessions.get(activityToken);
 
         if (session == null) {
-            session = createSessionByTokenLocked(activityToken);
-        } else {
-            if (DEBUG) Slog.d(TAG, "reusing session for " + activityToken + ": " + session.mId);
+            Slog.w(TAG, "finishSessionLocked(): no session for " + activityToken);
+            return;
         }
 
-        session.updateAutoFillInput(flags, autoFillId, null, bounds);
+        mUi.hideFillUi();
+        session.showSaveLocked();
     }
 
-    private Session getSessionByTokenLocked(IBinder activityToken) {
-        final int size = mSessions.size();
-        for (int i = 0; i < size; i++) {
-            final Session session = mSessions.valueAt(i);
-            if (activityToken.equals(session.mActivityToken.get())) {
-                return session;
-            }
-        }
-        return null;
-    }
+    private Session createSessionByTokenLocked(IBinder activityToken, IBinder appCallbackToken) {
 
-    private Session createSessionByTokenLocked(IBinder activityToken) {
-        final int sessionId = ++sSessionIdCounter;
-        if (DEBUG) Slog.d(TAG, "creating session for " + activityToken + ": " + sessionId);
-
-        final Session newSession = new Session(sessionId, activityToken);
-        mSessions.put(sessionId, newSession);
+        final Session newSession = new Session(mContext, activityToken, appCallbackToken);
+        mSessions.put(activityToken, newSession);
 
         /*
          * TODO(b/33197203): apply security checks below:
@@ -385,7 +247,9 @@
          */
         try {
             // TODO(b/33197203): add MetricsLogger call
-            if (!mAm.requestAutoFillData(mAssistReceiver, null, sessionId, activityToken)) {
+            final Bundle receiverExtras = new Bundle();
+            receiverExtras.putBinder(EXTRA_ACTIVITY_TOKEN, activityToken);
+            if (!mAm.requestAutoFillData(mAssistReceiver, receiverExtras, activityToken)) {
                 // 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);
@@ -396,94 +260,53 @@
         return newSession;
     }
 
-    /**
-     * Callback indicating the value of a field change in the app.
-     */
-    void onValueChangeLocked(IBinder activityToken, AutoFillId autoFillId, AutoFillValue newValue) {
+    void updateSessionLocked(IBinder activityToken, AutoFillId autoFillId, Rect bounds,
+            AutoFillValue value, int flags) {
+
         // TODO(b/33197203): add MetricsLogger call
-        final Session session = getSessionByTokenLocked(activityToken);
+        final Session session = mSessions.get(activityToken);
         if (session == null) {
-            Slog.w(TAG, "onValueChangeLocked(): session gone for " + activityToken);
+            Slog.w(TAG, "updateSessionLocked(): session gone for " + activityToken);
             return;
         }
 
-        session.updateValueLocked(autoFillId, newValue);
+        session.updateLocked(autoFillId, bounds, value, flags);
     }
 
-    void stopLocked() {
-        if (DEBUG) Slog.d(TAG, "stopLocked()");
+    private void handleSessionSave(IBinder activityToken) {
 
-        // Sanity check.
-        if (mService == null) {
-            Slog.w(TAG, "service already null on shutdown");
-            return;
-        }
-        try {
-            mService.onDisconnected();
-        } catch (RemoteException e) {
-            if (! (e instanceof DeadObjectException)) {
-                Slog.w(TAG, "Exception calling service.onDisconnected(): " + e);
+        synchronized (mLock) {
+            final Session session = mSessions.get(activityToken);
+            if (session == null) {
+                Slog.w(TAG, "handleSessionSave(): already gone: " + activityToken);
+
+                return;
             }
-        } finally {
-            mService = null;
-        }
-
-        if (mBound) {
-            mContext.unbindService(mConnection);
-            mBound = false;
-        }
-        if (mValid) {
-            mContext.unregisterReceiver(mBroadcastReceiver);
+            session.callSaveLocked();
         }
     }
 
-    void removeSessionLocked(int id) {
-        if (DEBUG) Slog.d(TAG, "Removing session " + id);
-        mSessions.remove(id);
+    void destroyLocked() {
+        if (VERBOSE) Slog.v(TAG, "destroyLocked()");
 
-        // TODO(b/33197203): notify mService so it can invalidate the FillCallback / SaveCallback
-        // and cached AssistStructures
+        mContext.unregisterReceiver(mBroadcastReceiver);
+        for (Session session : mSessions.values()) {
+            session.destroyLocked();
+        }
+        mSessions.clear();
     }
 
     void dumpLocked(String prefix, PrintWriter pw) {
-        if (!mValid) {
-            pw.print("  NOT VALID: ");
-            if (mInfo == null) {
-                pw.println("no info");
-            } else {
-                pw.println(mInfo.getParseError());
-            }
-            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(mComponentName);
-        pw.print(prefix); pw.print("mService: "); pw.println(mService);
-        pw.print(prefix); pw.print("mBound="); pw.println(mBound);
-        pw.print(prefix); pw.print("mEstimateTimeOfDeath=");
-            TimeUtils.formatDuration(mEstimateTimeOfDeath, SystemClock.uptimeMillis(), pw);
-            pw.println();
-        pw.print(prefix); pw.print("mAuthToken: "); pw.println(mAuthToken);
+        pw.print(prefix); pw.println("Component:"); pw.println(mComponentName);
 
-        if (DEBUG) {
+        if (VERBOSE) {
             // ServiceInfo dump is too noisy and redundant (it can be obtained through other dumps)
             pw.print(prefix); pw.println("ServiceInfo:");
             mInfo.getServiceInfo().dump(new PrintWriterPrinter(pw), prefix + prefix);
         }
 
-        if (mQueuedRequests.isEmpty()) {
-            pw.print(prefix); pw.println("No queued requests");
-        } else {
-            pw.print(prefix); pw.println("Queued requests:");
-            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("sSessionIdCounter="); pw.println(sSessionIdCounter);
         final int size = mSessions.size();
         if (size == 0) {
             pw.print(prefix); pw.println("No sessions");
@@ -498,32 +321,10 @@
 
     @Override
     public String toString() {
-        return "AutoFillManagerServiceImpl: [userId=" + mUserId + ", uid=" + mUid
+        return "AutoFillManagerServiceImpl: [userId=" + mUserId
                 + ", component=" + mComponentName + "]";
     }
 
-    private static final class QueuedRequest {
-        final IBinder activityToken;
-        final AutoFillId autoFillId;
-        final Rect bounds;
-        final int flags;
-
-        QueuedRequest(IBinder activityToken, AutoFillId autoFillId, Rect bounds, int flags) {
-            this.activityToken = activityToken;
-            this.autoFillId = autoFillId;
-            this.bounds = bounds;
-            this.flags = flags;
-        }
-
-        @Override
-        public String toString() {
-            if (!DEBUG) return super.toString();
-
-            return "QueuedRequest: [flags=" + flags + ", token=" + activityToken
-                    + ", id=" + autoFillId + ", bounds=" + bounds;
-        }
-    }
-
     /**
      * State for a given view with a AutoFillId.
      *
@@ -539,13 +340,17 @@
                     @Nullable AutoFillValue value);
         }
 
+        final AutoFillId mId;
         private final Listener mListener;
         // // TODO(b/33197203): does it really need a reference to the session's response?
         private FillResponse mResponse;
         private AutoFillValue mAutoFillValue;
         private Rect mBounds;
 
-        ViewState(Listener listener) {
+        private boolean mValueUpdated;
+
+        ViewState(AutoFillId id, Listener listener) {
+            mId = id;
             mListener = listener;
         }
 
@@ -553,15 +358,13 @@
          * Response should only be set once.
          */
         void setResponse(FillResponse response) {
-            if (mResponse != null) {
-                Slog.e(TAG, "ViewState response set more than once");
-                return;
-            }
             mResponse = response;
-
             maybeCallOnFillReady();
         }
 
+        // TODO(b/33197203): need to refactor / rename / document this method to make it clear that
+        // it can change  the value and update the UI; similarly, should replace code that
+        // directly sets mAutoFilLValue to use encapsulation.
         void update(@Nullable AutoFillValue autoFillValue, @Nullable Rect bounds) {
             if (autoFillValue != null) {
                 mAutoFillValue = autoFillValue;
@@ -587,9 +390,17 @@
         public String toString() {
             if (!DEBUG) return super.toString();
 
-            return "ViewState: [response=" + mResponse + ", value=" + mAutoFillValue
-                    + ", bounds=" + mBounds + "]";
+            return "ViewState: [id=" + mId + ", value=" + mAutoFillValue + ", bounds=" + mBounds
+                    + ", updated = " + mValueUpdated + "]";
         }
+
+        void dump(String prefix, PrintWriter pw) {
+            pw.print(prefix); pw.print("id:" ); pw.println(mId);
+            pw.print(prefix); pw.print("value:" ); pw.println(mAutoFillValue);
+            pw.print(prefix); pw.print("updated:" ); pw.println(mValueUpdated);
+            pw.print(prefix); pw.print("bounds:" ); pw.println(mBounds);
+        }
+
     }
 
     /**
@@ -608,280 +419,202 @@
     // - On all authentication scenarios.
     // - When user does not interact back after a while.
     // - When service is unbound.
-    final class Session implements ViewState.Listener {
-
-        private final AutoFillUI mUi;
-        private final WeakReference<IBinder> mActivityToken;
+    final class Session implements RemoteFillService.FillServiceCallbacks, ViewState.Listener,
+            AutoFillUI.AutoFillUiCallback {
+        private final IBinder mActivityToken;
 
         @GuardedBy("mLock")
         private final Map<AutoFillId, ViewState> mViewStates = new ArrayMap<>();
+
         @GuardedBy("mLock")
         @Nullable
         private ViewState mCurrentViewState;
 
-        private IAutoFillAppCallback mAppCallback;
+        private final IAutoFillAppCallback mAppCallback;
+
+        @GuardedBy("mLock")
+        RemoteFillService mRemoteFillService;
 
         // TODO(b/33197203): Get a response per view instead of per activity.
         @GuardedBy("mLock")
         private FillResponse mCurrentResponse;
-        @GuardedBy("mLock")
-        private FillResponse mResponseRequiringAuth;
-        @GuardedBy("mLock")
-        private Dataset mDatasetRequiringAuth;
-
-        /**
-         * Used to auto-fill the activity directly when the FillCallback.onResponse() is called as
-         * the result of a successful user authentication on service's side.
-         */
-        @GuardedBy("mLock")
-        private boolean mAutoFillDirectly;
 
         /**
          * Used to remember which {@link Dataset} filled the session.
          */
+        // TODO(b/33197203): might need more than one once we support partitions
         @GuardedBy("mLock")
         private Dataset mAutoFilledDataset;
 
         /**
-         * Map of ids that must be updated so they're send to {@link #onSaveLocked()}.
-         */
-        @GuardedBy("mLock")
-        private Map<AutoFillId, AutoFillValue> mUpdatedValues;
-
-        /**
          * Assist structure sent by the app; it will be updated (sanitized, change values for save)
          * before sent to {@link AutoFillService}.
          */
+        @GuardedBy("mLock")
         private AssistStructure mStructure;
 
-        // TODO(b/33197203): use handler to handle results?
-        // TODO(b/33197203): handle all callback methods and/or cancelation?
-        private IFingerprintServiceReceiver mServiceReceiver =
-                new IFingerprintServiceReceiver.Stub() {
+        private Session(Context context, IBinder activityToken, IBinder appCallback) {
+            mRemoteFillService = new RemoteFillService(context, mComponent, mUserId, this);
+            mActivityToken = activityToken;
 
-            @Override
-            public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
-                if (DEBUG) Slog.d(TAG, "onEnrollResult()");
-            }
-
-            @Override
-            public void onAcquired(long deviceId, int acquiredInfo, int vendorCode) {
-                if (DEBUG) Slog.d(TAG, "onAcquired()");
-            }
-
-            @Override
-            public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
-                if (DEBUG) Slog.d(TAG, "onAuthenticationSucceeded(): " + fp.getGroupId());
-
-                // First, check what was authenticated, a response or a dataset.
-                // Then, decide how to handle it:
-                // - If service provided data, handle them directly.
-                // - Otherwise, notify service.
-
-                mAutoFillDirectly = true;
-
-                if (mDatasetRequiringAuth != null) {
-                    if (mDatasetRequiringAuth.isEmpty()) {
-                        notifyDatasetAuthenticationResult(mDatasetRequiringAuth.getExtras(),
-                                FLAG_AUTHENTICATION_SUCCESS);
-                    } else {
-                        autoFillApp(mDatasetRequiringAuth);
-                    }
-                } else if (mResponseRequiringAuth != null) {
-                    final List<Dataset> datasets = mResponseRequiringAuth.getDatasets();
-                    if (datasets.isEmpty()) {
-                        notifyResponseAuthenticationResult(mResponseRequiringAuth.getExtras(),
-                                FLAG_AUTHENTICATION_SUCCESS);
-                    } else {
-                        showResponseLocked(mResponseRequiringAuth, true);
-                    }
-                } else {
-                    Slog.w(TAG, "onAuthenticationSucceeded(): no response or dataset");
-                }
-
-                mUi.dismissFingerprintRequest(true);
-            }
-
-            @Override
-            public void onAuthenticationFailed(long deviceId) {
-                if (DEBUG) Slog.d(TAG, "onAuthenticationFailed()");
-                // Do nothing - onError() will be called after a few failures...
-            }
-
-            @Override
-            public void onError(long deviceId, int error, int vendorCode) {
-                if (DEBUG) Slog.d(TAG, "onError()");
-
-                // Notify service so it can fallback to its own authentication
-                if (mDatasetRequiringAuth != null) {
-                    notifyDatasetAuthenticationResult(mDatasetRequiringAuth.getExtras(),
-                            FLAG_AUTHENTICATION_ERROR);
-                } else if (mResponseRequiringAuth != null) {
-                    notifyResponseAuthenticationResult(mResponseRequiringAuth.getExtras(),
-                            FLAG_AUTHENTICATION_ERROR);
-                } else {
-                    Slog.w(TAG, "onError(): no response or dataset");
-                }
-
-                mUi.dismissFingerprintRequest(false);
-            }
-
-            @Override
-            public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
-                if (DEBUG) Slog.d(TAG, "onRemoved()");
-            }
-
-            @Override
-            public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
-                if (DEBUG) Slog.d(TAG, "onEnumerated()");
-            }
-        };
-
-        private IAutoFillServerCallback mServerCallback = new IAutoFillServerCallback.Stub() {
-            @Override
-            public void showResponse(FillResponse response) {
-                // TODO(b/33197203): add MetricsLogger call
-                if (response == null) {
-                    if (DEBUG) Slog.d(TAG, "showResponse(): null response");
+            mAppCallback = IAutoFillAppCallback.Stub.asInterface(appCallback);
+            try {
+                appCallback.linkToDeath(() -> {
+                    if (DEBUG) Slog.d(TAG, "app binder died");
 
                     removeSelf();
-                    return;
-                }
-
-                synchronized (mLock) {
-                    showResponseLocked(response, response.isAuthRequired());
-                }
+                }, 0);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "linkToDeath() on mAppCallback failed: " + e);
             }
+        }
 
-            @Override
-            public void showError(CharSequence message) {
-                // TODO(b/33197203): add MetricsLogger call
-                if (DEBUG) Slog.d(TAG, "showError(): " + message);
 
-                mUi.showError(message);
+        // FillServiceCallbacks
+        @Override
+        public void onFillRequestSuccess(FillResponse response) {
+            // TODO(b/33197203): add MetricsLogger call
+            if (response == null) {
                 removeSelf();
+                return;
             }
-
-            @Override
-            public void onSaved() {
-                // TODO(b/33197203): add MetricsLogger call
-                if (DEBUG) Slog.d(TAG, "onSaved()");
-
-                removeSelf();
+            synchronized (mLock) {
+                processResponseLocked(response);
             }
+        }
 
-            @Override
-            public void unlockFillResponse(int flags) {
-                // TODO(b/33197203): add proper MetricsLogger calls?
-                if (DEBUG) Log.d(TAG, "unlockUser(): flags=" + flags);
+        // FillServiceCallbacks
+        @Override
+        public void onFillRequestFailure(CharSequence message) {
+            // TODO(b/33197203): add MetricsLogger call
+            getUiForShowing().showError(message);
+            removeSelf();
+        }
 
-                synchronized (mLock) {
-                    if ((flags & FLAG_AUTHENTICATION_SUCCESS) != 0) {
-                        if (mResponseRequiringAuth == null) {
-                            Log.wtf(TAG, "unlockUser(): no mResponseRequiringAuth on flags "
-                                    + flags);
-                            removeSelf();
-                            return;
-                        }
-                        final List<Dataset> datasets = mResponseRequiringAuth.getDatasets();
-                        if (datasets.isEmpty()) {
-                            Log.w(TAG, "unlockUser(): no dataset on previous response: "
-                                    + mResponseRequiringAuth);
-                            removeSelf();
-                            return;
-                        }
-                        mAutoFillDirectly = true;
-                        showResponseLocked(mResponseRequiringAuth, false);
-                    }
-                    // TODO(b/33197203): show UI error on authentication failure?
-                    // Or let service handle it?
-                }
-            }
+        // FillServiceCallbacks
+        @Override
+        public void onSaveRequestSuccess() {
+            // TODO(b/33197203): add MetricsLogger call
+            // Nothing left to do...
+            removeSelf();
+        }
 
-            @Override
-            public void unlockDataset(Dataset dataset, int flags) {
-                // TODO(b/33197203): add proper MetricsLogger calls?
-                if (DEBUG) Log.d(TAG, "unlockDataset(): dataset=" + dataset + ", flags=" + flags);
+        // FillServiceCallbacks
+        @Override
+        public void onSaveRequestFailure(CharSequence message) {
+            // TODO(b/33197203): add MetricsLogger call
+            getUiForShowing().showError(message);
+            removeSelf();
+        }
 
-                if ((flags & FLAG_AUTHENTICATION_SUCCESS) != 0) {
-                    autoFillApp(dataset != null ? dataset : mDatasetRequiringAuth);
-                    return;
-                }
-            }
-        };
+        // FillServiceCallbacks
+        @Override
+        public void authenticate(IntentSender intent, Intent fillInIntent) {
+            startAuthIntent(intent, fillInIntent);
+        }
 
-        final int mId;
+        // FillServiceCallbacks
+        @Override
+        public void onServiceDied(RemoteFillService service) {
+            // TODO(b/33197203): implement
+        }
 
-        private Session(int id, IBinder activityToken) {
-            mUi = new AutoFillUI(mContext, this);
-            mId = id;
-            mActivityToken = new WeakReference<>(activityToken);
+        // AutoFillUiCallback
+        @Override
+        public void fill(Dataset dataset) {
+            autoFill(dataset);
+        }
+
+        // AutoFillUiCallback
+        @Override
+        public void save() {
+            mHandlerCaller.getHandler().obtainMessage(MSG_SERVICE_SAVE, mActivityToken)
+                    .sendToTarget();
         }
 
         /**
-         * Callback used to indivate a field has been updated.
+         * Show the save UI, when session can be saved.
          */
-        void updateValueLocked(AutoFillId id, AutoFillValue newValue) {
-          if (DEBUG) Slog.d(TAG, "updateValueLocked(): id=" + id + ", newValue=" + newValue);
-
-          // TODO(b/33197203): ignore if not part of the savable ids.
-          if (mUpdatedValues == null) {
-                // Lazy intializes it
-                mUpdatedValues = new HashMap<>();
+        public void showSaveLocked() {
+            if (mStructure == null) {
+                // Sanity check; should not happen...
+                Slog.wtf(TAG, "showSaveLocked(): no mStructure");
+                return;
             }
-            mUpdatedValues.put(id, newValue);
+            final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
+            if (VERBOSE) Slog.v(TAG, "showSaveLocked(): savableIds=" + savableIds);
+
+            if (savableIds.isEmpty()) {
+                if (DEBUG) Slog.d(TAG, "showSaveLocked(): service doesn't want to save");
+                return;
+            }
+
+            final int size = savableIds.size();
+            for (int i = 0; i < size; i++) {
+                final AutoFillId id = savableIds.valueAt(i);
+                final ViewState state = mViewStates.get(id);
+                if (state != null && state.mValueUpdated) {
+                    final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
+                    if (state.mAutoFillValue == null || state.mAutoFillValue.equals(filledValue)) {
+                        continue;
+                    }
+                    if (DEBUG) {
+                        Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
+                                + state.mAutoFillValue);
+                    }
+
+                    mUi.showSaveUi();
+                    return;
+                }
+            }
+            // Nothing changed...
+            if (DEBUG) Slog.d(TAG, "showSaveLocked(): with no changes, comes no responsibilities");
         }
 
         /**
          * Calls service when user requested save.
          */
-        void onSaveLocked() {
-            if (DEBUG) Slog.d(TAG, "onSaveLocked(): mUpdateValues=" + mUpdatedValues);
+        private void callSaveLocked() {
+            if (DEBUG) Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
 
-            if (mStructure == null) {
-                // Sanity check; should not happen...
-                Slog.wtf(TAG, "onSaveLocked(): no mStructure");
-                return;
-            }
+            // TODO(b/33197203): hookup extras and make sure they're tested by CTS
+            final Bundle extras = null;
+//            // TODO(b/33197203): make sure the extras are tested by CTS
+//            final Bundle responseExtras = mCurrentResponse == null ? null
+//                    : mCurrentResponse.getExtras();
+//            final Bundle datasetExtras = mAutoFilledDataset == null ? null
+//                    : mAutoFilledDataset.getExtras();
+//            final Bundle extras = (responseExtras == null && datasetExtras == null)
+//                    ? null : new Bundle();
+//            if (responseExtras != null) {
+//                if (DEBUG) {
+//                    Slog.d(TAG, "response extras on save extras: "
+//                            + bundleToString(responseExtras));
+//                }
+//                extras.putBundle(AutoFillService.EXTRA_RESPONSE_EXTRAS, responseExtras);
+//            }
+//            if (datasetExtras != null) {
+//                if (DEBUG) {
+//                    Slog.d(TAG, "dataset extras on save extras: " + bundleToString(datasetExtras));
+//                }
+//                extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetExtras);
+//            }
 
-            if (mUpdatedValues == null || mUpdatedValues.isEmpty()) {
-                // Nothing changed
-                if (DEBUG) Slog.d(TAG, "onSave(): when no changes, comes no responsibilities");
 
-                return;
-            }
-
-            // TODO(b/33197203): make sure the extras are tested by CTS
-            final Bundle responseExtras = mCurrentResponse == null ? null
-                    : mCurrentResponse.getExtras();
-            final Bundle datasetExtras = mAutoFilledDataset == null ? null
-                    : mAutoFilledDataset.getExtras();
-            final Bundle extras = (responseExtras == null && datasetExtras == null)
-                    ? null : new Bundle();
-            if (responseExtras != null) {
-                if (DEBUG) {
-                    Slog.d(TAG, "response extras on save extras: "
-                            + bundleToString(responseExtras));
+            for (Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) {
+                final AutoFillValue value = entry.getValue().mAutoFillValue;
+                if (value == null) {
+                    if (VERBOSE) Slog.v(TAG, "callSaveLocked(): skipping " + entry.getKey());
+                    continue;
                 }
-                extras.putBundle(AutoFillService.EXTRA_RESPONSE_EXTRAS, responseExtras);
-            }
-            if (datasetExtras != null) {
-                if (DEBUG) {
-                    Slog.d(TAG, "dataset extras on save extras: " + bundleToString(datasetExtras));
-                }
-                extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetExtras);
-            }
-
-
-            for (Entry<AutoFillId, AutoFillValue> entry : mUpdatedValues.entrySet()) {
                 final AutoFillId id = entry.getKey();
                 final ViewNode node = findViewNodeByIdLocked(id);
                 if (node == null) {
-                    Slog.w(TAG, "onSaveLocked(): did not find node with id " + id);
+                    Slog.w(TAG, "callSaveLocked(): did not find node with id " + id);
                     continue;
                 }
-                final AutoFillValue value = entry.getValue();
-                if (DEBUG) Slog.d(TAG, "onSaveLocked(): updating " + id + " to " + value);
+                if (DEBUG) Slog.d(TAG, "callSaveLocked(): updating " + id + " to " + value);
+
                 node.updateAutoFillValue(value);
             }
 
@@ -891,59 +624,78 @@
                 Slog.v(TAG, "Dumping " + mStructure + " before calling service.save()");
                 mStructure.dump();
             }
-            try {
-                mService.save(mStructure, mServerCallback, extras);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Error calling save on service: " + e);
-                // TODO(b/33197203): invalidate session?
-            }
+
+            mRemoteFillService.onSaveRequest(mStructure, extras);
         }
 
-        void setAppCallbackLocked(IBinder appBinder) {
-            try {
-                appBinder.linkToDeath(() -> {
-                    if (DEBUG) Slog.d(TAG, "app callback died");
-                    // TODO(b/33197203): more cleanup here?
-                    mAppCallback = null;
-                }, 0);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "linkToDeath() failed: " + e);
-            }
-            mAppCallback = IAutoFillAppCallback.Stub.asInterface(appBinder);
-        }
+        void updateLocked(AutoFillId id, Rect bounds, AutoFillValue value, int flags) {
+            if (DEBUG) Slog.d(TAG, "updateLocked(): id=" + id + ", flags=" + flags);
 
-        void updateAutoFillInput(int flags, AutoFillId autoFillId,
-                @Nullable AutoFillValue autoFillValue, @Nullable Rect bounds) {
-            synchronized (mLock) {
-                ViewState viewState = mViewStates.get(autoFillId);
-                if (viewState == null) {
-                    viewState = new ViewState(this);
-                    mViewStates.put(autoFillId, viewState);
+            if (mAutoFilledDataset != null && (flags & FLAG_VALUE_CHANGED) == 0) {
+                // TODO(b/33197203): ignoring because we don't support partitions yet
+                if (DEBUG) Slog.d(TAG, "updateLocked(): ignoring " + flags + " after auto-filled");
+                return;
+            }
+
+            ViewState viewState = mViewStates.get(id);
+            if (viewState == null) {
+                viewState = new ViewState(id, this);
+                mViewStates.put(id, viewState);
+            }
+
+            if ((flags & FLAG_START_SESSION) != 0 ) {
+                // View is triggering auto-fill.
+                mCurrentViewState = viewState;
+                viewState.update(value, bounds);
+                return;
+            }
+
+            if ((flags & FLAG_VALUE_CHANGED) != 0 && value != null &&
+                    !value.equals(viewState.mAutoFillValue)) {
+                viewState.mValueUpdated = true;
+
+                // Must check if this update was caused by auto-filling the view, in which
+                // case we just update the value, but not the UI.
+                if (mAutoFilledDataset != null) {
+                    final AutoFillValue filledValue = findValue(mAutoFilledDataset, id);
+                    if (value.equals(filledValue)) {
+                        viewState.mAutoFillValue = value;
+                        return;
+                    }
                 }
 
-                if ((flags & FLAG_UPDATE_UI_SHOW) != 0) {
-                    // Remove the UI if the ViewState has changed.
-                    if (mCurrentViewState != viewState) {
-                        mUi.hideFillUi();
-                        mCurrentViewState = viewState;
-                    }
-
-                    // If the ViewState is ready to be displayed, onReady() will be called.
-                    viewState.update(autoFillValue, bounds);
-
-                    // TODO(b/33197203): Remove when there is a response per activity.
-                    if (mCurrentResponse != null) {
-                        viewState.setResponse(mCurrentResponse);
-                    }
-                } else if ((flags & FLAG_UPDATE_UI_HIDE) != 0) {
-                    if (mCurrentViewState == viewState) {
-                        mUi.hideFillUi();
-                        mCurrentViewState = null;
-                    }
-                } else {
-                    Slog.w(TAG, "unknown flags " + flags);
-                }
+                // Just change value, don't update the UI
+                viewState.mAutoFillValue = value;
+                return;
             }
+
+            if ((flags & FLAG_FOCUS_GAINED) != 0) {
+                // Remove the UI if the ViewState has changed.
+                if (mCurrentViewState != viewState) {
+                    mUi.hideFillUi();
+                    mCurrentViewState = viewState;
+                }
+
+                // If the ViewState is ready to be displayed, onReady() will be called.
+                viewState.update(value, bounds);
+
+                // TODO(b/33197203): Remove when there is a response per activity.
+                if (mCurrentResponse != null) {
+                    viewState.setResponse(mCurrentResponse);
+                }
+
+                return;
+            }
+
+            if ((flags & FLAG_FOCUS_LOST) != 0) {
+                if (mCurrentViewState == viewState) {
+                    mUi.hideFillUi();
+                    mCurrentViewState = null;
+                }
+                return;
+            }
+
+            Slog.w(TAG, "unknown flags " + flags);
         }
 
         @Override
@@ -957,181 +709,168 @@
                     filterText = text.toString();
                 }
             }
-            mUi.showFillUi(viewState, response.getDatasets(), bounds, filterText);
+            getUiForShowing().showFillUi(viewState, response.getDatasets(), bounds, filterText);
         }
 
-        private void showResponseLocked(FillResponse response, boolean authRequired) {
-            if (DEBUG) Slog.d(TAG, "showResponse(directly=" + mAutoFillDirectly
-                    + ", authRequired=" + authRequired +"):" + response);
+        private void processResponseLocked(FillResponse response) {
+            if (DEBUG) Slog.d(TAG, "processResponseLocked(authRequired="
+                    + response.getAuthentication() +"):" + response);
 
-            if (mAutoFillDirectly && response != null) {
-                final List<Dataset> datasets = response.getDatasets();
-                if (datasets.size() == 1) {
-                    // User authenticated and provider returned just 1 dataset - auto-fill it now!
-                    final Dataset dataset = datasets.get(0);
-                    if (DEBUG) Slog.d(TAG, "auto-filling directly from auth: " + dataset);
+            // TODO(b/33197203): add MetricsLogger calls
 
-                    autoFillApp(dataset);
-                    return;
-                }
+            mCurrentResponse = response;
+
+            if (mCurrentResponse.getAuthentication() != null) {
+                // Handle authentication.
+                final Intent fillInIntent = createAuthFillInIntent(response.getId(), mStructure,
+                        new Bundle(), new FillCallback(new IFillCallback.Stub() {
+                            @Override
+                            public void onCancellable(ICancellationSignal cancellation) {
+                                // TODO(b/33197203): Handle cancellation
+                            }
+
+                            @Override
+                            public void onSuccess(FillResponse response) {
+                                mCurrentResponse = createAuthenticatedResponse(
+                                        mCurrentResponse, response);
+                                processResponseLocked(mCurrentResponse);
+                            }
+
+                            @Override
+                            public void onFailure(CharSequence message) {
+                                getUiForShowing().showError(message);
+                                removeSelf();
+                            }
+                        }));
+
+                 getUiForShowing().showFillResponseAuthRequest(
+                         mCurrentResponse.getAuthentication(), fillInIntent);
+                 return;
             }
 
-            if (!authRequired) {
-                // TODO(b/33197203): add MetricsLogger call
-                mCurrentResponse = response;
-                // TODO(b/33197203): Consider using mCurrentResponse, depends on partitioning design
-                if (mCurrentViewState != null) {
-                    mCurrentViewState.setResponse(mCurrentResponse);
-                }
+            final ArraySet<AutoFillId> savableIds = mCurrentResponse.getSavableIds();
+            if (savableIds == null || savableIds.isEmpty()) {
+                // NOTE: it's assuming the response has no datasets, since when a dataset is added
+                // it's view id is automatically added to savable_ids
+                if (DEBUG) Slog.d(TAG, "processResponseLocked(): nothing to do");
+
+                removeSelf();
                 return;
             }
 
-            // Handles response that requires authentication.
-            // TODO(b/33197203): add MetricsLogger call, including if fingerprint requested
-
-            mResponseRequiringAuth = response;
-            final boolean requiresFingerprint = response.hasCryptoObject();
-            if (requiresFingerprint) {
-                // TODO(b/33197203): check if fingerprint is available first and call error callback
-                // with FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE if it's not.
-                // Start scanning for the fingerprint.
-                scanFingerprint(response.getCryptoObjectOpId());
+            // TODO(b/33197203): Consider using mCurrentResponse, depends on partitioning design
+            if (mCurrentViewState != null) {
+                mCurrentViewState.setResponse(mCurrentResponse);
             }
-            // Displays the message asking the user to tap (or fingerprint) for AutoFill.
-            mUi.showFillResponseAuthenticationRequest(requiresFingerprint,
-                    response.getExtras(), response.getFlags());
         }
 
         void autoFill(Dataset dataset) {
             synchronized (mLock) {
                 // Autofill it directly...
-                if (!dataset.isAuthRequired()) {
+                if (dataset.getAuthentication() == null) {
                     autoFillApp(dataset);
                     return;
                 }
 
                 // ...or handle authentication.
-
-                mDatasetRequiringAuth = dataset;
-                final boolean requiresFingerprint = dataset.hasCryptoObject();
-                if (requiresFingerprint) {
-                    // TODO(b/33197203): check if fingerprint is available first and call error
-                    // callback with FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE if it's not.
-                    // Start scanning for the fingerprint.
-                    scanFingerprint(dataset.getCryptoObjectOpId());
-                    // Displays the message asking the user to tap (or fingerprint) for AutoFill.
-                    mUi.showDatasetFingerprintAuthenticationRequest(dataset);
-                } else {
-                    try {
-                        mService.authenticateDataset(dataset.getExtras(),
-                                FLAG_AUTHENTICATION_REQUESTED);
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "Error authenticating dataset: " + e);
+                Intent fillInIntent = createAuthFillInIntent(dataset.getId(), mStructure,
+                        new Bundle(), new FillCallback(new IFillCallback.Stub() {
+                    @Override
+                    public void onCancellable(ICancellationSignal cancellation) {
+                        // TODO(b/33197203): Handle cancellation
                     }
-                }
+
+                    @Override
+                    public void onSuccess(FillResponse response) {
+                        mCurrentResponse = createAuthenticatedResponse(
+                                mCurrentResponse, response);
+                        final Dataset augmentedDataset = Helper.findDatasetById(dataset.getId(),
+                                mCurrentResponse);
+                        if (augmentedDataset != null) {
+                            autoFill(augmentedDataset);
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(CharSequence message) {
+                        getUiForShowing().showError(message);
+                        removeSelf();
+                    }
+                }));
+
+                startAuthIntent(dataset.getAuthentication(), fillInIntent);
+            }
+        }
+
+        private Intent createAuthFillInIntent(String itemId, AssistStructure structure,
+                Bundle extras, FillCallback fillCallback) {
+            Intent fillInIntent = new Intent();
+            fillInIntent.putExtra(Intent.EXTRA_AUTO_FILL_ITEM_ID, itemId);
+            fillInIntent.putExtra(Intent.EXTRA_AUTO_FILL_ASSIST_STRUCTURE, structure);
+            fillInIntent.putExtra(Intent.EXTRA_AUTO_FILL_EXTRAS, extras);
+            fillInIntent.putExtra(Intent.EXTRA_AUTO_FILL_CALLBACK, fillCallback);
+            return fillInIntent;
+        }
+
+        private void startAuthIntent(IntentSender intent, Intent fillInIntent) {
+            try {
+                mAppCallback.startIntentSender(intent, fillInIntent);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Error launching auth intent", e);
             }
         }
 
         void dumpLocked(String prefix, PrintWriter pw) {
-            pw.print(prefix); pw.print("mId: "); pw.println(mId);
-            pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken.get());
+            pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
             pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse);
-            pw.print(prefix);
-                pw.print("mResponseRequiringAuth: "); pw.println(mResponseRequiringAuth);
-            pw.print(prefix);
-                pw.print("mDatasetRequiringAuth: "); pw.println(mDatasetRequiringAuth);
-            pw.print(prefix); pw.print("mAutoFillDirectly: "); pw.println(mAutoFillDirectly);
+            pw.print(prefix); pw.print("mAutoFilledDataset: "); pw.println(mAutoFilledDataset);
             pw.print(prefix); pw.print("mCurrentViewStates: "); pw.println(mCurrentViewState);
             pw.print(prefix); pw.print("mViewStates: "); pw.println(mViewStates.size());
             final String prefix2 = prefix + "  ";
             for (Map.Entry<AutoFillId, ViewState> entry : mViewStates.entrySet()) {
-                pw.print(prefix2);
-                pw.print(entry.getKey()); pw.print(": " ); pw.println(entry.getValue());
+                pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey());
+                entry.getValue().dump(prefix2, pw);
             }
-            pw.print(prefix); pw.print("mUpdatedValues: "); pw.println(mUpdatedValues);
-            pw.print(prefix); pw.print("mStructure: " );
-            // TODO(b/33197203): add method do dump AssistStructure on pw
-            if (mStructure != null) {
-                pw.println("look at logcat" );
-                mStructure.dump(); // dumps to logcat
-            } else {
-                pw.println("null");
-            }
-        }
-
-        /**
-         * Notifies the result of a {@link FillResponse} authentication request to the service.
-         *
-         * <p>Typically called by the UI after user taps the "Tap to autofill" affordance, or after user
-         * used the fingerprint sensors to authenticate.
-         */
-        void notifyResponseAuthenticationResult(Bundle extras, int flags) {
-            if (DEBUG) Slog.d(TAG, "notifyResponseAuthenticationResult(): flags=" + flags
-                    + ", extras=" + bundleToString(extras));
-            synchronized (mLock) {
-                try {
-                    mService.authenticateFillResponse(extras, flags);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Error sending authentication result back to service: " + e);
+            if (VERBOSE) {
+                pw.print(prefix); pw.print("mStructure: " );
+                // TODO(b/33197203): add method do dump AssistStructure on pw
+                if (mStructure != null) {
+                    pw.println("look at logcat" );
+                    mStructure.dump(); // dumps to logcat
+                } else {
+                    pw.println("null");
                 }
             }
-        }
 
-        /**
-         * Notifies the result of a {@link Dataset} authentication request to the service.
-         *
-         * <p>Typically called by the UI after user taps the "Tap to autofill" affordance, or after
-         * it gets the results from a fingerprint authentication.
-         */
-        void notifyDatasetAuthenticationResult(Bundle extras, int flags) {
-            if (DEBUG) Slog.d(TAG, "notifyDatasetAuthenticationResult(): flags=" + flags
-                    + ", extras=" + bundleToString(extras));
-            synchronized (mLock) {
-                try {
-                    mService.authenticateDataset(extras, flags);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Error sending authentication result back to service: " + e);
-                }
-            }
+            mRemoteFillService.dump(prefix, pw);
         }
 
         void autoFillApp(Dataset dataset) {
             synchronized (mLock) {
                 try {
                     if (DEBUG) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
+
                     mAppCallback.autoFill(dataset);
+                    mAutoFilledDataset = dataset;
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Error auto-filling activity: " + e);
                 }
             }
         }
 
-        /**
-         * Called by UI to trigger a save request to the service.
-         */
-        void requestSave() {
-            synchronized (mLock) {
-                onSaveLocked();
+        void enableSessionLocked() {
+            if (DEBUG) Slog.d(TAG, "enableSessionLocked()");
+
+            try {
+                mAppCallback.enableSession();
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error enabling session: " + e);
             }
         }
 
-        private void scanFingerprint(long opId) {
-            // TODO(b/33197203): add MetricsLogger call
-            if (DEBUG) Slog.d(TAG, "Starting fingerprint scan for op id: " + opId);
-
-            // TODO(b/33197203): since we're clearing the AutoFillService's identity, make sure
-            // this method is only called at the proper times, otherwise a malicious provider could
-            // keep the callback refence to bypass the check
-            final long token = Binder.clearCallingIdentity();
-            try {
-                // TODO(b/33197203): set a timeout?
-                mFingerprintService.authenticate(mAuthToken, opId, mUserId, mServiceReceiver, 0,
-                        null);
-            } catch (RemoteException e) {
-                // Local call, shouldn't happen.
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+        private AutoFillUI getUiForShowing() {
+            mUi.setCallback(this, mActivityToken);
+            return mUi;
         }
 
         private ViewNode findViewNodeByIdLocked(AutoFillId id) {
@@ -1167,10 +906,95 @@
             return null;
         }
 
+        private void destroyLocked() {
+            mRemoteFillService.destroy();
+            mUi.hideAll();
+            mUi.setCallback(null, null);
+        }
+
         private void removeSelf() {
+            if (VERBOSE) Slog.v(TAG, "removeSelf()");
+
             synchronized (mLock) {
-                removeSessionLocked(mId);
+                destroyLocked();
+                mSessions.remove(mActivityToken);
             }
         }
+
+        /**
+         * Creates a response from the {@code original} and an {@code update} by
+         * replacing all items that needed authentication (response or datasets)
+         * with their updated version if the latter does not need authentication.
+         * New datasets that don't require auth are appended.
+         *
+         * @param original The original response requiring auth at some level.
+         * @param update An updated response with auth not needed anymore at some level.
+         * @return A new response with updated items where auth is not needed anymore.
+         */
+        // TODO(b/33197203) Unit test
+        FillResponse createAuthenticatedResponse(FillResponse original, FillResponse update) {
+            // Can update only if ids match
+            if (!original.getId().equals(update.getId())) {
+                return original;
+            }
+
+            // If the original required auth and the update doesn't, the update wins
+            // but only if none of the update's datasets requires authentication.
+            if (original.getAuthentication() != null && update.getAuthentication() == null) {
+                ArraySet<Dataset> updateDatasets = update.getDatasets();
+                final int udpateDatasetCount = updateDatasets.size();
+                for (int i = 0; i < udpateDatasetCount; i++) {
+                    Dataset updateDataset = updateDatasets.valueAt(i);
+                    if (updateDataset.getAuthentication() != null) {
+                        return original;
+                    }
+                }
+                return update;
+            }
+
+            // If no auth on response level we create a response that has all
+            // datasets from the original with the ones that required auth but
+            // not anymore updated and new ones not requiring auth appended.
+
+            // The update shouldn't require auth
+            if (update.getAuthentication() != null) {
+                return original;
+            }
+
+            final FillResponse.Builder builder = new FillResponse.Builder(original.getId());
+
+            // Update existing datasets
+            final ArraySet<Dataset> origDatasets = original.getDatasets();
+            final int origDatasetCount = origDatasets.size();
+            for (int i = 0; i < origDatasetCount; i++) {
+                Dataset origDataset = origDatasets.valueAt(i);
+                ArraySet<Dataset> updateDatasets = update.getDatasets();
+                final int updateDatasetCount = updateDatasets.size();
+                for (int j = 0; j < updateDatasetCount; j++) {
+                    Dataset updateDataset = updateDatasets.valueAt(j);
+                    if (origDataset.getId().equals(updateDataset.getId())) {
+                        // The update shouldn't require auth
+                        if (updateDataset.getAuthentication() == null) {
+                            origDataset = updateDataset;
+                            updateDatasets.removeAt(j);
+                        }
+                        break;
+                    }
+                }
+                builder.addDataset(origDataset);
+            }
+
+            // Add new datasets
+            final ArraySet<Dataset> updateDatasets = update.getDatasets();
+            final int updateDatasetCount = updateDatasets.size();
+            for (int i = 0; i < updateDatasetCount; i++) {
+                final Dataset updateDataset = updateDatasets.valueAt(i);
+                builder.addDataset(updateDataset);
+            }
+
+            // For now no extras and savable id updates.
+
+            return builder.build();
+        }
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index 5c6009a..201a889 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -40,8 +40,6 @@
         final PrintWriter pw = getOutPrintWriter();
         try {
             switch (cmd) {
-                case "fill":
-                    return requestAutoFill();
                 case "save":
                     return requestSave();
                 default:
@@ -60,20 +58,12 @@
             pw.println("  help");
             pw.println("    Prints this help text.");
             pw.println("");
-            pw.println("  fill [--user USER_ID]");
-            pw.println("    Request provider to auto-fill the top activity. ");
             pw.println("  save [--user USER_ID]");
             pw.println("    Request provider to save contents of the top activity. ");
             pw.println("");
         }
     }
 
-    private int requestAutoFill() throws RemoteException {
-        final int userId = getUserIdFromArgs();
-        mService.requestAutoFillForUser(userId);
-        return 0;
-    }
-
     private int requestSave() throws RemoteException {
         final int userId = getUserIdFromArgs();
         mService.requestSaveForUser(userId);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
index 76c2916..c482c40 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -15,13 +15,9 @@
  */
 package com.android.server.autofill;
 
-
 import static com.android.server.autofill.Helper.DEBUG;
 
-import android.annotation.Nullable;
-import android.app.Activity;
 import android.app.Notification;
-import android.app.Notification.Action;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
@@ -29,12 +25,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.graphics.Rect;
-import android.graphics.PixelFormat;
 import android.os.Binder;
-import android.os.Bundle;
+import android.os.IBinder;
+import android.util.ArraySet;
+import android.os.Looper;
+import android.text.format.DateUtils;
 import android.util.Slog;
-import android.view.autofill.AutoFillId;
 import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 import android.view.Gravity;
@@ -44,27 +42,31 @@
 import android.view.WindowManager.LayoutParams;
 import android.widget.Toast;
 
-import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.HandlerCaller;
 import com.android.server.UiThread;
-import com.android.server.autofill.AutoFillManagerServiceImpl.Session;
 import com.android.server.autofill.AutoFillManagerServiceImpl.ViewState;
 
 import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.List;
 
 /**
  * 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 static final long SNACK_BAR_LIFETIME_MS = 30 * DateUtils.SECOND_IN_MILLIS;
+    private static final int MSG_HIDE_SNACK_BAR = 1;
+
+    private static final String EXTRA_AUTH_INTENT_SENDER =
+            "com.android.server.autofill.extra.AUTH_INTENT_SENDER";
+    private static final String EXTRA_AUTH_FILL_IN_INTENT =
+            "com.android.server.autofill.extra.AUTH_FILL_IN_INTENT";
 
     private final Context mContext;
-    private final Session mSession;
     private final WindowManager mWm;
 
+    // TODO(b/33197203) Fix locking - some state requires lock and some not - requires refactoring
+
     // Fill UI variables
     private AnchoredWindow mFillWindow;
     private DatasetPicker mFillView;
@@ -72,21 +74,47 @@
     private Rect mBounds;
     private String mFilterText;
 
+    private AutoFillUiCallback mCallback;
+    private IBinder mActivityToken;
+
+    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+        switch (msg.what) {
+            case MSG_HIDE_SNACK_BAR: {
+                hideSnackbarUiThread();
+                return;
+            }
+            default: {
+                Slog.w(TAG, "Invalid message: " + msg);
+            }
+        }
+    };
+    private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(),
+            mHandlerCallback, true);
+
     /**
      * Custom snackbar UI used for saving autofill or other informational messages.
      */
     private View mSnackbar;
 
-    AutoFillUI(Context context, Session session) {
+    AutoFillUI(Context context) {
         mContext = context;
-        mSession = session;
         mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
     }
 
+    void setCallback(AutoFillUiCallback callback, IBinder activityToken) {
+        hideAll();
+        mCallback = callback;
+        mActivityToken = activityToken;
+    }
+
     /**
      * Displays an error message to the user.
      */
     void showError(CharSequence message) {
+        if (!hasCallback()) {
+            return;
+        }
+        hideAll();
         // TODO(b/33197203): proper implementation
         UiThread.getHandler().runWithScissors(() -> {
             Toast.makeText(mContext, "AutoFill error: " + message, Toast.LENGTH_LONG).show();
@@ -95,21 +123,17 @@
 
     /**
      * Hides the fill UI.
-     * Shows the options from a {@link FillResponse} so the user can pick up the proper
-     * {@link Dataset} (when the response has one) for a given view (identified by
-     * {@code autoFillId}).
      */
     void hideFillUi() {
         UiThread.getHandler().runWithScissors(() -> {
-            hideFillUiLocked();
+            hideFillUiUiThread();
         }, 0);
     }
 
-    // Must be called in inside UI Thread
-    private void hideFillUiLocked() {
+    @android.annotation.UiThread
+    private void hideFillUiUiThread() {
         if (mFillWindow != null) {
-            if (DEBUG) Slog.d(TAG, "hideFillUiLocked(): hide" + mFillWindow);
-
+            if (DEBUG) Slog.d(TAG, "hideFillUiUiThread(): hide" + mFillWindow);
             mFillWindow.hide();
         }
 
@@ -120,7 +144,6 @@
         mFillWindow = null;
     }
 
-
     /**
      * Shows the fill UI, removing the previous fill UI if the has changed.
      *
@@ -129,26 +152,45 @@
      * @param bounds bounds of the view to be filled, used if changed
      * @param filterText text of the view to be filled, used if changed
      */
-    void showFillUi(ViewState viewState, List<Dataset> datasets, Rect bounds,
+    void showFillUi(ViewState viewState, ArraySet<Dataset> datasets, Rect bounds,
             String filterText) {
-        UiThread.getHandler().runWithScissors(() -> {
-            if (mViewState != viewState) {
-                // new
-                hideFillUi();
+        if (!hasCallback()) {
+            return;
+        }
 
+        if (datasets == null) {
+            // TODO(b/33197203): shouldn't be called, but keeping the WTF for a while just to be
+            // safe, otherwise it would crash system server...
+            Slog.wtf(TAG, "showFillUI(): no dataset");
+            return;
+        }
+
+        // TODO(b/33197203): call to hideAll() was making it janky because then mViewState is set
+        // to null and hence the first check inside the lambada fails, causing it to be displayed
+        // twice in some cases.
+        hideAll();
+
+        UiThread.getHandler().runWithScissors(() -> {
+            if (mViewState == null || !mViewState.mId.equals(viewState.mId)) {
                 mViewState = viewState;
 
                 mFillView = new DatasetPicker(mContext, datasets,
                         (dataset) -> {
-                            mSession.autoFillApp(dataset);
+                            final AutoFillUiCallback callback;
+                            synchronized (mLock) {
+                                callback = mCallback;
+                            }
+                            callback.fill(dataset);
                             hideFillUi();
                         });
+                // TODO(b/33197203): No magical numbers
                 mFillWindow = new AnchoredWindow(
                         mWm, mFillView, 800, ViewGroup.LayoutParams.WRAP_CONTENT);
 
-                if (DEBUG) Slog.d(TAG, "show FillUi");
+                if (DEBUG) Slog.d(TAG, "show FillUi: " + viewState.mId);
             }
 
+            // TODO(b/33197203): If bounds are the same we would not show, fix this
             if (!bounds.equals(mBounds)) {
                 if (DEBUG) Slog.d(TAG, "update FillUi bounds: " + mBounds);
                 mBounds = bounds;
@@ -170,27 +212,14 @@
      * <p>It typically replaces the auto-fill bar with a message saying "Press fingerprint or tap to
      * autofill" or "Tap to autofill", depending on the value of {@code usesFingerprint}.
      */
-    void showFillResponseAuthenticationRequest(boolean usesFingerprint,
-            Bundle extras, int flags) {
-        // TODO(b/33197203): proper implementation
-        showAuthNotification(usesFingerprint, extras, flags);
-    }
-
-    /**
-     * Shows an UI affordance asking indicating that user action is required before a
-     * {@link Dataset} can be used.
-     *
-     * <p>It typically replaces the auto-fill bar with a message saying "Press fingerprint to
-     * autofill".
-     */
-    void showDatasetFingerprintAuthenticationRequest(Dataset dataset) {
-        if (DEBUG) Slog.d(TAG, "showDatasetAuthenticationRequest(): dataset=" + dataset);
-
-        // TODO(b/33197203): proper implementation (either pop up a fingerprint dialog or replace
-        // the auto-fill bar with a new message.
+    void showFillResponseAuthRequest(IntentSender intent, Intent fillInIntent) {
+        if (!hasCallback()) {
+            return;
+        }
+        hideAll();
         UiThread.getHandler().runWithScissors(() -> {
-            Toast.makeText(mContext, "AutoFill: press fingerprint to unlock " + dataset.getName(),
-                    Toast.LENGTH_LONG).show();
+            // TODO(b/33197203): proper implementation
+            showFillResponseAuthUiUiThread(intent, fillInIntent);
         }, 0);
     }
 
@@ -198,46 +227,37 @@
      * Shows the UI asking the user to save for auto-fill.
      */
     void showSaveUi() {
-        showSnackbar(new SavePrompt(mContext, new SavePrompt.OnSaveListener() {
-            @Override
-            public void onSaveClick() {
-                hideSnackbar();
-
-                // TODO(b/33197203): add MetricsLogger call
-                mSession.requestSave();
-            }
-            @Override
-            public void onCancelClick() {
-                hideSnackbar();
-            }
-        }));
-    }
-
-    /**
-     * Called by service after the user user the fingerprint sensors to authenticate.
-     */
-    void dismissFingerprintRequest(boolean success) {
-        if (DEBUG) Slog.d(TAG, "dismissFingerprintRequest(): ok=" + success);
-
-        dismissAuthNotification();
-
-        if (!success) {
-            // TODO(b/33197203): proper implementation (snack bar / i18n string)
-            UiThread.getHandler().runWithScissors(() -> {
-                Toast.makeText(mContext, "AutoFill: fingerprint failed", Toast.LENGTH_LONG).show();
-            }, 0);
+        if (!hasCallback()) {
+            return;
         }
+        hideAll();
+        UiThread.getHandler().runWithScissors(() -> {
+            showSnackbarUiThread(new SavePrompt(mContext,
+                    new SavePrompt.OnSaveListener() {
+                @Override
+                public void onSaveClick() {
+                    hideSnackbarUiThread();
+                    // TODO(b/33197203): add MetricsLogger call
+                    mCallback.save();
+                }
+
+                @Override
+                public void onCancelClick() {
+                    // TODO(b/33197203): add MetricsLogger call
+                    hideSnackbarUiThread();
+                }
+            }));
+        }, 0);
     }
 
     /**
-     * Closes all UI affordances.
+     * Hides all UI affordances.
      */
-    void closeAll() {
-        if (DEBUG) Slog.d(TAG, "closeAll()");
-
+    void hideAll() {
         UiThread.getHandler().runWithScissors(() -> {
-            hideSnackbarLocked();
-            hideFillUiLocked();
+            hideSnackbarUiThread();
+            hideFillUiUiThread();
+            hideFillResponseAuthUiUiThread();
         }, 0);
     }
 
@@ -245,7 +265,7 @@
         pw.println("AufoFill UI");
         final String prefix = "  ";
         pw.print(prefix); pw.print("sResultCode: "); pw.println(sResultCode);
-        pw.print(prefix); pw.print("mSessionId: "); pw.println(mSession.mId);
+        pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
         pw.print(prefix); pw.print("mViewState: "); pw.println(mViewState);
         pw.print(prefix); pw.print("mBounds: "); pw.println(mBounds);
@@ -254,7 +274,7 @@
 
     //similar to a snackbar, but can be a bit custom since it is more than just text. This will
     //allow two buttons for saving or not saving the autofill for instance as well.
-    private void showSnackbar(View snackBar) {
+    private void showSnackbarUiThread(View snackBar) {
         final LayoutParams params = new LayoutParams();
         params.setTitle("AutoFill Save");
         params.type = LayoutParams.TYPE_PHONE; // TODO(b/33197203) use app window token
@@ -272,22 +292,34 @@
             mSnackbar = snackBar;
             mWm.addView(mSnackbar, params);
         }, 0);
+
+        if (DEBUG) {
+            Slog.d(TAG, "showSnackbar(): auto dismissing it in " + SNACK_BAR_LIFETIME_MS + " ms");
+        }
+        mHandlerCaller.sendMessageDelayed(mHandlerCaller.obtainMessage(MSG_HIDE_SNACK_BAR),
+                SNACK_BAR_LIFETIME_MS);
     }
 
-    private void hideSnackbar() {
-        UiThread.getHandler().runWithScissors(() -> {
-            hideSnackbarLocked();
-        }, 0);
-    }
-
-    // Must be called in inside UI Thread
-    private void hideSnackbarLocked() {
+    private void hideSnackbarUiThread() {
+        mHandlerCaller.getHandler().removeMessages(MSG_HIDE_SNACK_BAR);
         if (mSnackbar != null) {
             mWm.removeView(mSnackbar);
             mSnackbar = null;
         }
     }
 
+    private boolean hasCallback() {
+        synchronized (mLock) {
+            return mCallback != null;
+        }
+    }
+
+    interface AutoFillUiCallback {
+        void authenticate(IntentSender intent, Intent fillInIntent);
+        void fill(Dataset dataset);
+        void save();
+    }
+
     /////////////////////////////////////////////////////////////////////////////////
     // 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.     //
@@ -297,25 +329,13 @@
     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_SESSION_ID = "session_id";
-    private static final String EXTRA_FILL_RESPONSE = "fill_response";
-    private static final String EXTRA_DATASET = "dataset";
-    private static final String EXTRA_AUTH_REQUIRED_EXTRAS = "auth_required_extras";
-    private static final String EXTRA_FLAGS = "flags";
-
-    private static final String TYPE_OPTIONS = "options";
-    private static final String TYPE_AUTH_RESPONSE = "auth_response";
-
     private BroadcastReceiver mNotificationReceiver;
     private final Object mLock = new Object();
 
     // Hack used to generate unique pending intents
     static int sResultCode = 0;
 
-    private void setNotificationListener() {
+    private void ensureNotificationListener() {
         synchronized (mLock) {
             if (mNotificationReceiver == null) {
                 mNotificationReceiver = new NotificationReceiver();
@@ -328,83 +348,58 @@
     final class NotificationReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            final String type = intent.getStringExtra(EXTRA_NOTIFICATION_TYPE);
-            if (type == null) {
-                Slog.wtf(TAG, "No extra " + EXTRA_NOTIFICATION_TYPE + " on intent " + intent);
-                return;
-            }
-            final Dataset dataset = intent.getParcelableExtra(EXTRA_DATASET);
-            final int flags = intent.getIntExtra(EXTRA_FLAGS, 0);
-
-            if (DEBUG) Slog.d(TAG, "Notification received: type=" + type
-                    + ", sessionId=" + mSession.mId);
+            final AutoFillUiCallback callback;
             synchronized (mLock) {
-                switch (type) {
-                    case TYPE_AUTH_RESPONSE:
-                        mSession.notifyResponseAuthenticationResult(
-                                intent.getBundleExtra(EXTRA_AUTH_REQUIRED_EXTRAS), flags);
-                        break;
-                    default: {
-                        Slog.w(TAG, "Unknown notification type: " + type);
-                    }
-                }
+                callback = mCallback;
+            }
+            if (callback != null) {
+                IntentSender intentSender = intent.getParcelableExtra(EXTRA_AUTH_INTENT_SENDER);
+                Intent fillInIntent = intent.getParcelableExtra(EXTRA_AUTH_FILL_IN_INTENT);
+                callback.authenticate(intentSender, fillInIntent);
             }
             collapseStatusBar();
         }
     }
 
-    private static Intent newNotificationIntent(String type) {
-        final Intent intent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
-        intent.putExtra(EXTRA_NOTIFICATION_TYPE, type);
-        return intent;
-    }
-
-    private void showAuthNotification(boolean usesFingerprint,
-            Bundle extras, int flags) {
-        final long token = Binder.clearCallingIdentity();
-        try {
-            showAuthNotificationAsSystem(usesFingerprint, extras, flags);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    private void showAuthNotificationAsSystem(
-            boolean usesFingerprint, Bundle extras, int flags) {
+    @android.annotation.UiThread
+    private void showFillResponseAuthUiUiThread(IntentSender intent, Intent fillInIntent) {
         final String title = "AutoFill Authentication";
         final StringBuilder subTitle = new StringBuilder("Provider require user authentication.\n");
 
-        final Intent authIntent = newNotificationIntent(TYPE_AUTH_RESPONSE);
-        if (extras != null) {
-            authIntent.putExtra(EXTRA_AUTH_REQUIRED_EXTRAS, extras);
-        }
-        if (flags != 0) {
-            authIntent.putExtra(EXTRA_FLAGS, flags);
-        }
-        final PendingIntent authPendingIntent = PendingIntent.getBroadcast(mContext, ++sResultCode,
-                authIntent, PendingIntent.FLAG_ONE_SHOT);
+        final Intent authIntent = new Intent(NOTIFICATION_AUTO_FILL_INTENT);
+        authIntent.putExtra(EXTRA_AUTH_INTENT_SENDER, intent);
+        authIntent.putExtra(EXTRA_AUTH_FILL_IN_INTENT, fillInIntent);
 
-        if (usesFingerprint) {
-            subTitle.append("But kindly accepts your fingerprint instead"
-                    + "\n(tap fingerprint sensor to trigger it)");
+        final PendingIntent authPendingIntent = PendingIntent.getBroadcast(
+                mContext, ++sResultCode, authIntent, PendingIntent.FLAG_ONE_SHOT);
 
-        } else {
-            subTitle.append("Tap notification to launch its authentication UI.");
-        }
+        subTitle.append("Tap notification to launch its authentication UI.");
 
         final Notification.Builder notification = newNotificationBuilder()
                 .setAutoCancel(true)
                 .setOngoing(false)
                 .setContentTitle(title)
-                .setStyle(new Notification.BigTextStyle().bigText(subTitle.toString()));
-        if (authPendingIntent != null) {
-            notification.setContentIntent(authPendingIntent);
+                .setStyle(new Notification.BigTextStyle().bigText(subTitle.toString()))
+                .setContentIntent(authPendingIntent);
+
+        ensureNotificationListener();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            NotificationManager.from(mContext).notify(0, notification.build());
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
-        NotificationManager.from(mContext).notify(mSession.mId, notification.build());
     }
 
-    private void dismissAuthNotification() {
-        NotificationManager.from(mContext).cancel(mSession.mId);
+    @android.annotation.UiThread
+    private void hideFillResponseAuthUiUiThread() {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            NotificationManager.from(mContext).cancel(0);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     private Notification.Builder newNotificationBuilder() {
diff --git a/services/autofill/java/com/android/server/autofill/DatasetPicker.java b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
index 7245aaa..8212cf1 100644
--- a/services/autofill/java/com/android/server/autofill/DatasetPicker.java
+++ b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
@@ -17,6 +17,7 @@
 
 import android.content.Context;
 import android.graphics.Color;
+import android.util.ArraySet;
 import android.view.autofill.Dataset;
 import android.view.View;
 import android.view.ViewGroup;
@@ -38,15 +39,13 @@
  * 3) the View is detached.
  */
 final class DatasetPicker extends ListView implements OnItemClickListener {
-    private static final String TAG = "DatasetPicker";
-
     interface Listener {
         void onDatasetPicked(Dataset dataset);
     }
 
     private final Listener mListener;
 
-    DatasetPicker(Context context, List<Dataset> datasets, Listener listener) {
+    DatasetPicker(Context context, ArraySet<Dataset> datasets, Listener listener) {
         super(context);
         mListener = listener;
 
@@ -80,7 +79,7 @@
         adapter.getFilter().filter(prefix, new FilterListener() {
             @Override
             public void onFilterComplete(int count) {
-                DatasetPicker.this.requestLayout();
+                setVisibility(count > 0 ? View.VISIBLE : View.GONE);
             }
         });
     }
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 9171dac..7400a64 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -16,8 +16,15 @@
 
 package com.android.server.autofill;
 
+import android.annotation.Nullable;
 import android.os.Bundle;
+import android.util.ArraySet;
+import android.view.autofill.AutoFillId;
+import android.view.autofill.AutoFillValue;
+import android.view.autofill.Dataset;
+import android.view.autofill.FillResponse;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Objects;
 import java.util.Set;
@@ -52,6 +59,46 @@
         return builder.toString();
     }
 
+    /**
+     * Gets the value of a {@link Dataset} field by its id, or {@code null} if not found.
+     */
+    @Nullable
+    static AutoFillValue findValue(Dataset dataset, AutoFillId id) {
+        if (dataset != null) {
+            final ArrayList<AutoFillId> ids = dataset.getFieldIds();
+            final int size = ids.size();
+            for (int i = 0; i < size; i++) {
+                if (id.equals(ids.get(i))) {
+                    return dataset.getFieldValues().get(i);
+                }
+
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Finds a data set by id in a response.
+     *
+     * @param id The dataset id.
+     * @param response The response to search.
+     * @return The dataset if found or null.
+     */
+    static Dataset findDatasetById(String id, FillResponse response) {
+        ArraySet<Dataset> datasets = response.getDatasets();
+        if (datasets == null || datasets.isEmpty()) {
+            return null;
+        }
+        final int datasetCount = datasets.size();
+        for (int i = 0; i < datasetCount; i++) {
+            Dataset dataset = datasets.valueAt(i);
+            if (dataset.getId().equals(id)) {
+                return dataset;
+            }
+        }
+        return null;
+    }
+
     private Helper() {
         throw new UnsupportedOperationException("contains static members only");
     }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
new file mode 100644
index 0000000..c070f77
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
+import android.os.ICancellationSignal;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.autofill.AutoFillService;
+import android.service.autofill.IAutoFillService;
+import android.service.autofill.IFillCallback;
+import android.service.autofill.ISaveCallback;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.autofill.FillResponse;
+import com.android.internal.os.HandlerCaller;
+import com.android.server.FgThread;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+
+/**
+ * This class represents a remote fill service. It abstracts away the binding
+ * and unbinding from the remote implementation.
+ *
+ * <p>Clients can call methods of this class without worrying about when and
+ * how to bind/unbind/timeout. All state of this class is modified on a handler
+ * thread.
+ */
+final class RemoteFillService implements DeathRecipient {
+    private static final String LOG_TAG = "RemoteFillService";
+
+    private static final boolean DEBUG = Helper.DEBUG;
+
+    // How long after the last interaction with the service we would unbind
+    private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.MINUTE_IN_MILLIS;
+
+    private final Context mContext;
+
+    private final ComponentName mComponentName;
+
+    private final Intent mIntent;
+
+    private final FillServiceCallbacks mCallbacks;
+
+    private final int mUserId;
+
+    private final ServiceConnection mServiceConnection = new RemoteServiceConnection();
+
+    private final HandlerCaller mHandler;
+
+    private IAutoFillService mAutoFillService;
+
+    private boolean mBinding;
+
+    private boolean mDestroyed;
+
+    private boolean mServiceDied;
+
+    private boolean mCompleted;
+
+    private PendingRequest mPendingRequest;
+
+    public interface FillServiceCallbacks {
+        void onFillRequestSuccess(FillResponse response);
+        void onFillRequestFailure(CharSequence message);
+        void onSaveRequestSuccess();
+        void onSaveRequestFailure(CharSequence message);
+        void onServiceDied(RemoteFillService service);
+    }
+
+    public RemoteFillService(Context context, ComponentName componentName,
+            int userId, FillServiceCallbacks callbacks) {
+        mContext = context;
+        mCallbacks = callbacks;
+        mComponentName = componentName;
+        mIntent = new Intent(AutoFillService.SERVICE_INTERFACE)
+                .setComponent(mComponentName);
+        mUserId = userId;
+        mHandler = new MyHandler(context);
+    }
+
+    public void destroy() {
+        mHandler.obtainMessage(MyHandler.MSG_DESTROY).sendToTarget();
+    }
+
+    private void handleDestroy() {
+        if (mPendingRequest != null) {
+            mPendingRequest.cancel();
+            mPendingRequest = null;
+        }
+        ensureUnbound();
+        mDestroyed = true;
+    }
+
+    @Override
+    public void binderDied() {
+        mHandler.obtainMessage(MyHandler.MSG_BINDER_DIED).sendToTarget();
+    }
+
+    private void handleBinderDied() {
+        if (mAutoFillService != null) {
+            mAutoFillService.asBinder().unlinkToDeath(this, 0);
+        }
+        mAutoFillService = null;
+        mServiceDied = true;
+        mCallbacks.onServiceDied(this);
+    }
+
+    public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+        cancelScheduledUnbind();
+        PendingFillRequest request = new PendingFillRequest(structure, extras, this);
+        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+    }
+
+    public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+        cancelScheduledUnbind();
+        PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
+        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+    }
+
+    // Note: we are dumping without a lock held so this is a bit racy but
+    // adding a lock to a class that offloads to a handler thread would
+    // mean adding a lock adding overhead to normal runtime operation.
+    public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+        String tab = "  ";
+        pw.append(prefix).append("service:").println();
+        pw.append(prefix).append(tab).append("userId=")
+                .append(String.valueOf(mUserId)).println();
+        pw.append(prefix).append(tab).append("componentName=")
+                .append(mComponentName.flattenToString()).println();
+        pw.append(prefix).append(tab).append("destroyed=")
+                .append(String.valueOf(mDestroyed)).println();
+        pw.append(prefix).append(tab).append("bound=")
+                .append(String.valueOf(isBound())).println();
+        pw.append(prefix).append(tab).append("hasPendingRequest=")
+                .append(String.valueOf(mPendingRequest != null)).println();
+        pw.println();
+    }
+
+    private void cancelScheduledUnbind() {
+        mHandler.removeMessages(MyHandler.MSG_UNBIND);
+    }
+
+    private void scheduleUnbind() {
+        cancelScheduledUnbind();
+        Message message = mHandler.obtainMessage(MyHandler.MSG_UNBIND);
+        mHandler.sendMessageDelayed(message, TIMEOUT_IDLE_BIND_MILLIS);
+    }
+
+    private void handleUnbind() {
+        ensureUnbound();
+    }
+
+    private void handlePendingRequest(PendingRequest pendingRequest) {
+        if (mDestroyed || mCompleted) {
+            return;
+        }
+        if (pendingRequest.isFinal()) {
+            mCompleted = true;
+        }
+        if (!isBound()) {
+            if (mPendingRequest != null) {
+                mPendingRequest.cancel();
+            }
+            mPendingRequest = pendingRequest;
+            ensureBound();
+        } else {
+            if (DEBUG) {
+                Slog.d(LOG_TAG, "[user: " + mUserId + "] handleOnFillRequest()");
+            }
+            pendingRequest.run();
+        }
+    }
+
+    private boolean isBound() {
+        return mAutoFillService != null;
+    }
+
+    private void ensureBound() {
+        if (isBound() || mBinding) {
+            return;
+        }
+        if (DEBUG) {
+            Slog.d(LOG_TAG, "[user: " + mUserId + "] ensureBound()");
+        }
+        mBinding = true;
+
+        boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection,
+                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+                new UserHandle(mUserId));
+
+        if (!willBind) {
+            if (DEBUG) {
+                Slog.d(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent);
+            }
+            mBinding = false;
+
+            if (!mServiceDied) {
+                handleBinderDied();
+            }
+        }
+    }
+
+    private void ensureUnbound() {
+        if (!isBound() && !mBinding) {
+            return;
+        }
+        if (DEBUG) {
+            Slog.d(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()");
+        }
+        mBinding = false;
+        if (isBound()) {
+            mAutoFillService.asBinder().unlinkToDeath(this, 0);
+            mAutoFillService = null;
+        }
+        mContext.unbindService(mServiceConnection);
+    }
+
+    private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest,
+            FillResponse response) {
+        mHandler.getHandler().post(() -> {
+            if (handleResponseCallbackCommon(pendingRequest)) {
+                mCallbacks.onFillRequestSuccess(response);
+            }
+        });
+    }
+
+    private void dispatchOnFillRequestFailure(PendingRequest pendingRequest,
+            CharSequence message) {
+        mHandler.getHandler().post(() -> {
+            if (handleResponseCallbackCommon(pendingRequest)) {
+                mCallbacks.onFillRequestFailure(message);
+            }
+        });
+    }
+
+    private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest) {
+        mHandler.getHandler().post(() -> {
+            if (handleResponseCallbackCommon(pendingRequest)) {
+                mCallbacks.onSaveRequestSuccess();
+            }
+        });
+    }
+
+    private void dispatchOnSaveRequestFailure(PendingRequest pendingRequest,
+            CharSequence message) {
+        mHandler.getHandler().post(() -> {
+            if (handleResponseCallbackCommon(pendingRequest)) {
+                mCallbacks.onSaveRequestFailure(message);
+            }
+        });
+    }
+
+    private boolean handleResponseCallbackCommon(PendingRequest pendingRequest) {
+        if (mDestroyed) {
+            return false;
+        }
+        if (mPendingRequest == pendingRequest) {
+            mPendingRequest = null;
+        }
+        if (mPendingRequest == null) {
+            scheduleUnbind();
+        }
+        return true;
+    }
+
+    private class RemoteServiceConnection implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (mDestroyed || !mBinding) {
+                mContext.unbindService(mServiceConnection);
+                return;
+            }
+            mBinding = false;
+            mAutoFillService = IAutoFillService.Stub.asInterface(service);
+            try {
+                service.linkToDeath(RemoteFillService.this, 0);
+            } catch (RemoteException re) {
+                handleBinderDied();
+                return;
+            }
+
+            if (mPendingRequest != null) {
+                handlePendingRequest(mPendingRequest);
+            }
+
+            mServiceDied = false;
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mBinding = true;
+            mAutoFillService = null;
+        }
+    }
+
+    private final class MyHandler extends HandlerCaller {
+        public static final int MSG_DESTROY = 1;
+        public static final int MSG_BINDER_DIED = 2;
+        public static final int MSG_UNBIND = 3;
+        public static final int MSG_ON_PENDING_REQUEST = 4;
+
+        public MyHandler(Context context) {
+            // Cannot use lambda - doesn't compile
+            super(context, FgThread.getHandler().getLooper(), new Callback() {
+                @Override
+                public void executeMessage(Message message) {
+                    if (mDestroyed) {
+                        Slog.w(LOG_TAG, "Not handling " + message + " as service for "
+                                + mComponentName + " is already destroyed");
+                        return;
+                    }
+                    switch (message.what) {
+                        case MSG_DESTROY: {
+                            handleDestroy();
+                        } break;
+
+                        case MSG_BINDER_DIED: {
+                            handleBinderDied();
+                        } break;
+
+                        case MSG_UNBIND: {
+                            handleUnbind();
+                        } break;
+
+                        case MSG_ON_PENDING_REQUEST: {
+                            handlePendingRequest((PendingRequest) message.obj);
+                        } break;
+                    }
+                }
+            }, false);
+        }
+    }
+
+    private static abstract class PendingRequest implements Runnable {
+        void cancel() {
+
+        }
+
+        /**
+         * @return whether this request leads to a final state where no
+         * other requests can be made.
+         */
+        boolean isFinal() {
+            return false;
+        }
+    }
+
+    private static final class PendingFillRequest extends PendingRequest {
+        private final Object mLock = new Object();
+        private final WeakReference<RemoteFillService> mWeakService;
+        private AssistStructure mStructure;
+        private Bundle mExtras;
+        private final IFillCallback mCallback;
+        private ICancellationSignal mCancellation;
+        private boolean mCancelled;
+
+        public PendingFillRequest(AssistStructure structure,
+                Bundle extras, RemoteFillService service) {
+            mStructure = structure;
+            mExtras = extras;
+            mWeakService = new WeakReference<>(service);
+            mCallback = new IFillCallback.Stub() {
+                @Override
+                public void onCancellable(ICancellationSignal cancellation) {
+                    synchronized (mLock) {
+                        final boolean cancelled;
+                        synchronized (mLock) {
+                            mCancellation = cancellation;
+                            cancelled = mCancelled;
+                        }
+                        if (cancelled) {
+                            try {
+                                cancellation.cancel();
+                            } catch (RemoteException e) {
+                                Slog.e(LOG_TAG, "Error requesting a cancellation", e);
+                            }
+                        }
+                    }
+                }
+
+                @Override
+                public void onSuccess(FillResponse response) {
+                    RemoteFillService remoteService = mWeakService.get();
+                    if (remoteService != null) {
+                        remoteService.dispatchOnFillRequestSuccess(
+                                PendingFillRequest.this, response);
+                    }
+                }
+
+                @Override
+                public void onFailure(CharSequence message) {
+                    RemoteFillService remoteService = mWeakService.get();
+                    if (remoteService != null) {
+                        remoteService.dispatchOnFillRequestFailure(
+                                PendingFillRequest.this, message);
+                    }
+                }
+            };
+        }
+
+        @Override
+        public void run() {
+            RemoteFillService remoteService = mWeakService.get();
+            if (remoteService != null) {
+                try {
+                    remoteService.mAutoFillService.onFillRequest(mStructure,
+                            mExtras, mCallback);
+                    synchronized (mLock) {
+                        mStructure = null;
+                        mExtras = null;
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(LOG_TAG, "Error calling on fill request", e);
+                    cancel();
+                }
+            }
+        }
+
+        @Override
+        public void cancel() {
+            final ICancellationSignal cancellation;
+            synchronized (mLock) {
+                if (mCancelled) {
+                    return;
+                }
+                mCancelled = true;
+                cancellation = mCancellation;
+            }
+            if (cancellation == null) {
+                return;
+            }
+            try {
+                cancellation.cancel();
+            } catch (RemoteException e) {
+                Slog.e(LOG_TAG, "Error cancelling a fill request", e);
+            }
+        }
+    }
+
+    private static final class PendingSaveRequest extends PendingRequest {
+        private final Object mLock = new Object();
+        private final WeakReference<RemoteFillService> mWeakService;
+        private AssistStructure mStructure;
+        private Bundle mExtras;
+        private final ISaveCallback mCallback;
+
+        public PendingSaveRequest(@NonNull AssistStructure structure,
+                @Nullable Bundle extras, @NonNull RemoteFillService service) {
+            mStructure = structure;
+            mExtras = extras;
+            mWeakService = new WeakReference<>(service);
+            mCallback = new ISaveCallback.Stub() {
+                @Override
+                public void onSuccess() {
+                    RemoteFillService service = mWeakService.get();
+                    if (service != null) {
+                        service.dispatchOnSaveRequestSuccess(
+                                PendingSaveRequest.this);
+                    }
+                }
+
+                @Override
+                public void onFailure(CharSequence message) {
+                    RemoteFillService service = mWeakService.get();
+                    if (service != null) {
+                        service.dispatchOnSaveRequestFailure(
+                                PendingSaveRequest.this, message);
+                    }
+                }
+            };
+        }
+
+        @Override
+        public void run() {
+            RemoteFillService service = mWeakService.get();
+            if (service != null) {
+                try {
+                    service.mAutoFillService.onSaveRequest(mStructure,
+                            mExtras, mCallback);
+                    synchronized (mLock) {
+                        mStructure = null;
+                        mExtras = null;
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(LOG_TAG, "Error calling on save request", e);
+                }
+            }
+        }
+
+        @Override
+        public boolean isFinal() {
+            return true;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 4ab894f..5646084 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -142,7 +142,7 @@
     private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
 
     // default background throttling interval if not overriden in settings
-    private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 10 * 60 * 1000;
+    private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
 
     // Location Providers may sometimes deliver location updates
     // slightly faster that requested - provide grace period so
diff --git a/services/core/java/com/android/server/LockSettingsStrongAuth.java b/services/core/java/com/android/server/LockSettingsStrongAuth.java
index 1314110..f5fe3db 100644
--- a/services/core/java/com/android/server/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/LockSettingsStrongAuth.java
@@ -51,6 +51,7 @@
     private static final int MSG_REGISTER_TRACKER = 2;
     private static final int MSG_UNREGISTER_TRACKER = 3;
     private static final int MSG_REMOVE_USER = 4;
+    private static final int MSG_SCHEDULE_STRONG_AUTH_TIMEOUT = 5;
 
     private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
             "LockSettingsStrongAuth.timeoutForUser";
@@ -128,6 +129,23 @@
         }
     }
 
+    private void handleScheduleStrongAuthTimeout(int userId) {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId);
+        // cancel current alarm listener for the user (if there was one)
+        StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
+        if (alarm != null) {
+            mAlarmManager.cancel(alarm);
+        } else {
+            alarm = new StrongAuthTimeoutAlarmListener(userId);
+            mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
+        }
+        // schedule a new alarm listener for the user
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG,
+                alarm, mHandler);
+    }
+
     private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
         for (int i = 0; i < mStrongAuthTrackers.size(); i++) {
             try {
@@ -151,7 +169,8 @@
     }
 
     public void removeUser(int userId) {
-        mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
+        final int argNotUsed = 0;
+        mHandler.obtainMessage(MSG_REMOVE_USER, userId, argNotUsed).sendToTarget();
     }
 
     public void requireStrongAuth(int strongAuthReason, int userId) {
@@ -169,29 +188,8 @@
     }
 
     public void reportSuccessfulStrongAuthUnlock(int userId) {
-        scheduleStrongAuthTimeout(userId);
-    }
-
-    private void scheduleStrongAuthTimeout(int userId) {
-        final DevicePolicyManager dpm =
-                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
-        long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId);
-        // cancel current alarm listener for the user (if there was one)
-        StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId);
-        if (alarm != null) {
-            mAlarmManager.cancel(alarm);
-        } else {
-            alarm = new StrongAuthTimeoutAlarmListener(userId);
-            mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm);
-        }
-        // schedule a new alarm listener for the user
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG,
-                    alarm, mHandler);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
+        final int argNotUsed = 0;
+        mHandler.obtainMessage(MSG_SCHEDULE_STRONG_AUTH_TIMEOUT, userId, argNotUsed).sendToTarget();
     }
 
     private class StrongAuthTimeoutAlarmListener implements OnAlarmListener {
@@ -224,6 +222,9 @@
                 case MSG_REMOVE_USER:
                     handleRemoveUser(msg.arg1);
                     break;
+                case MSG_SCHEDULE_STRONG_AUTH_TIMEOUT:
+                    handleScheduleStrongAuthTimeout(msg.arg1);
+                    break;
             }
         }
     };
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 22dbf44..5fe8b1a 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -927,7 +927,7 @@
                 try {
                     for (int i = 0; i < count; i++) {
                         consumer.accept(callbackList.getBroadcastItem(i),
-                                callbackList.getRegisteredCallbackCookie(i));
+                                callbackList.getBroadcastCookie(i));
                     }
                 } finally {
                     callbackList.finishBroadcast();
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 5370026..22543cb 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -599,7 +599,7 @@
             if (oldVersion == 2) {
                 // Remove uid based table and replace it with packageName based
                 db.execSQL("DROP TRIGGER IF EXISTS " + TABLE_ACCOUNTS + "DeleteVisibility");
-                db.execSQL("DROP TABLE IF EXISTS " + TABLE_ACCOUNTS);
+                db.execSQL("DROP TABLE IF EXISTS " + TABLE_VISIBILITY);
                 createAccountsVisibilityTable(db);
                 createAccountsDeletionVisibilityCleanupTrigger(db);
                 oldVersion++;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5655dc5..041fee2 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 
 import java.io.FileDescriptor;
@@ -1391,8 +1393,7 @@
         }
         if (r != null) {
             if (mAm.checkComponentPermission(r.permission,
-                    callingPid, callingUid, r.appInfo.uid, r.exported)
-                    != PackageManager.PERMISSION_GRANTED) {
+                    callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) {
                 if (!r.exported) {
                     Slog.w(TAG, "Permission Denial: Accessing service " + r.name
                             + " from pid=" + callingPid
@@ -2775,16 +2776,15 @@
         return info;
     }
 
-    List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum, int flags) {
+    List<ActivityManager.RunningServiceInfo> getRunningServiceInfoLocked(int maxNum, int flags,
+        int callingUid, boolean allowed) {
         ArrayList<ActivityManager.RunningServiceInfo> res
                 = new ArrayList<ActivityManager.RunningServiceInfo>();
 
-        final int uid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         try {
-            if (ActivityManager.checkUidPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
-                    uid) == PackageManager.PERMISSION_GRANTED) {
+            if (ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, callingUid)
+                == PERMISSION_GRANTED) {
                 int[] users = mAm.mUserController.getUsers();
                 for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
                     ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(users[ui]);
@@ -2802,16 +2802,20 @@
                     res.add(info);
                 }
             } else {
-                int userId = UserHandle.getUserId(uid);
+                int userId = UserHandle.getUserId(callingUid);
                 ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(userId);
                 for (int i=0; i<alls.size() && res.size() < maxNum; i++) {
                     ServiceRecord sr = alls.valueAt(i);
-                    res.add(makeRunningServiceInfoLocked(sr));
+
+                    if (allowed || (sr.app != null && sr.app.uid == callingUid)) {
+                        res.add(makeRunningServiceInfoLocked(sr));
+                    }
                 }
 
                 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
                     ServiceRecord r = mRestartingServices.get(i);
-                    if (r.userId == userId) {
+                    if (r.userId == userId
+                        && (allowed || (r.app != null && r.app.uid == callingUid))) {
                         ActivityManager.RunningServiceInfo info =
                                 makeRunningServiceInfoLocked(r);
                         info.restarting = r.nextRestartTime;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5ed8290..93fb911 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -701,18 +701,15 @@
         public AssistStructure structure = null;
         public AssistContent content = null;
         public Bundle receiverExtras;
-        public int resultCode;
 
         public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
-                String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _resultCode,
-                int _userHandle) {
+                String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _userHandle) {
             activity = _activity;
             extras = _extras;
             intent = _intent;
             hint = _hint;
             receiver = _receiver;
             receiverExtras = _receiverExtras;
-            resultCode = _resultCode;
             userHandle = _userHandle;
         }
         @Override
@@ -1627,10 +1624,6 @@
     int mThumbnailHeight;
     float mFullscreenThumbnailScale;
 
-    /** The aspect ratio bounds of the PIP. */
-    float mMinPipAspectRatio;
-    float mMaxPipAspectRatio;
-
     final ServiceThread mHandlerThread;
     final MainHandler mHandler;
     final UiHandler mUiHandler;
@@ -7665,12 +7658,13 @@
                     r.pictureInPictureArgs.copyOnlySet(args);
                     final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
                     final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
-                    final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
-                            ? mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY, aspectRatio)
-                            : mWindowManager.getPictureInPictureDefaultBounds(DEFAULT_DISPLAY);
+                    final Rect bounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
+                            aspectRatio);
                     mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
                             bounds, true /* moveHomeStackToFront */);
-                    mStackSupervisor.getStack(PINNED_STACK_ID).setPictureInPictureActions(actions);
+                    final ActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
+                    stack.setPictureInPictureAspectRatio(aspectRatio);
+                    stack.setPictureInPictureActions(actions);
 
                     MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_ENTERED,
                             r.supportsPictureInPictureWhilePausing);
@@ -7747,10 +7741,6 @@
         }
     }
 
-    private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
-        return mMinPipAspectRatio <= aspectRatio && aspectRatio <= mMaxPipAspectRatio;
-    }
-
     /**
      * Checks the state of the system and the activity associated with the given {@param token} to
      * verify that picture-in-picture is supported for that activity.
@@ -7781,10 +7771,15 @@
         }
 
         if (args.hasSetAspectRatio()
-                && !isValidPictureInPictureAspectRatio(args.getAspectRatio())) {
+                && !mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
+                        args.getAspectRatio())) {
+            final float minAspectRatio = mContext.getResources().getFloat(
+                    com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
+            final float maxAspectRatio = mContext.getResources().getFloat(
+                    com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
             throw new IllegalArgumentException(String.format(caller
                     + ": Aspect ratio is too extreme (must be between %f and %f).",
-                            mMinPipAspectRatio, mMaxPipAspectRatio));
+                            minAspectRatio, maxAspectRatio));
         }
 
         if (args.hasSetActions()
@@ -12457,7 +12452,7 @@
     @Override
     public Bundle getAssistContextExtras(int requestType) {
         PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
-                null, 0, null, true /* focused */, true /* newSessionId */,
+                null, null, true /* focused */, true /* newSessionId */,
                 UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
         if (pae == null) {
             return null;
@@ -12524,29 +12519,29 @@
     public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
             Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId) {
         return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
-                0, activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null,
+                activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null,
                 PENDING_ASSIST_EXTRAS_LONG_TIMEOUT) != null;
     }
 
     @Override
     public boolean requestAutoFillData(IResultReceiver receiver, Bundle receiverExtras,
-            int resultCode, IBinder activityToken) {
+            IBinder activityToken) {
         // 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).
         return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTO_FILL, null, null,
-                receiver, receiverExtras, resultCode, activityToken, true, true,
-                UserHandle.getCallingUserId(), null,
-                PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT) != null;
+                receiver, receiverExtras, activityToken, true, true, UserHandle.getCallingUserId(),
+                null, PENDING_AUTO_FILL_ASSIST_STRUCTURE_TIMEOUT) != null;
     }
 
     private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
-            IResultReceiver receiver, Bundle receiverExtras, int resultCode, IBinder activityToken,
+            IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken,
             boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout) {
         enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
                 "enqueueAssistContext()");
+
         synchronized (this) {
             ActivityRecord activity = getFocusedStack().topActivity();
             if (activity == null) {
@@ -12582,8 +12577,10 @@
             }
             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,
-                    resultCode, userHandle);
+                    userHandle);
+
             // Increment the sessionId if necessary
             if (newSessionId) {
                 mViSessionId++;
@@ -12666,15 +12663,11 @@
                 sendBundle.putParcelable(VoiceInteractionSession.KEY_CONTENT, pae.content);
                 sendBundle.putBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS,
                         pae.receiverExtras);
-                IBinder cb = extras.getBinder(AutoFillService.KEY_CALLBACK);
-                if (cb != null) {
-                    sendBundle.putBinder(AutoFillService.KEY_CALLBACK, cb);
-                }
             }
         }
         if (sendReceiver != null) {
             try {
-                sendReceiver.send(pae.resultCode, sendBundle);
+                sendReceiver.send(0, sendBundle);
             } catch (RemoteException e) {
             }
             return;
@@ -12699,7 +12692,7 @@
 
     public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
             Bundle args) {
-        return enqueueAssistContext(requestType, intent, hint, null, null, 0, null,
+        return enqueueAssistContext(requestType, intent, hint, null, null, null,
                 true /* focused */, true /* newSessionId */, userHandle, args,
                 PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
     }
@@ -13469,10 +13462,6 @@
                     com.android.internal.R.dimen.thumbnail_width);
             mThumbnailHeight = res.getDimensionPixelSize(
                     com.android.internal.R.dimen.thumbnail_height);
-            mMinPipAspectRatio = res.getFloat(
-                    com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
-            mMaxPipAspectRatio = res.getFloat(
-                    com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
             mAppErrors.loadAppsNotReportingCrashesFromConfigLocked(res.getString(
                     com.android.internal.R.string.config_appsNotReportingCrashes));
             mUserController.mUserSwitchUiEnabled = !res.getBoolean(
@@ -17467,7 +17456,11 @@
             int flags) {
         enforceNotIsolatedCaller("getServices");
         synchronized (this) {
-            return mServices.getRunningServiceInfoLocked(maxNum, flags);
+            final int callingUid = Binder.getCallingUid();
+            final boolean allowed = isGetTasksAllowed("getServices", Binder.getCallingPid(),
+                callingUid);
+
+            return mServices.getRunningServiceInfoLocked(maxNum, flags, callingUid, allowed);
         }
     }
 
@@ -22735,13 +22728,6 @@
         }
 
         @Override
-        public IBinder getTopVisibleActivity(int uid) {
-            synchronized (ActivityManagerService.this) {
-                return mStackSupervisor.getTopVisibleActivity(uid);
-            }
-        }
-
-        @Override
         public void notifyDockedStackMinimizedChanged(boolean minimized) {
             synchronized (ActivityManagerService.this) {
                 mStackSupervisor.setDockedStackMinimized(minimized);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 3573b8b..58c17eb 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -30,6 +30,7 @@
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
@@ -44,7 +45,10 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
 import static android.os.Build.VERSION_CODES.HONEYCOMB;
+import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
@@ -79,6 +83,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
@@ -2007,7 +2012,8 @@
                         + ", newGlobalConfig=" + newGlobalConfig
                         + ", newTaskMergedOverrideConfig=" + newTaskMergedOverrideConfig);
 
-        if ((changes&(~info.getRealConfigChanged())) != 0 || forceNewConfig) {
+        if (shouldRelaunchLocked(changes, newGlobalConfig, newTaskMergedOverrideConfig)
+                || forceNewConfig) {
             // Aha, the activity isn't handling the change, so DIE DIE DIE.
             configChangeFlags |= changes;
             startFreezingScreenLocked(app, globalChanges);
@@ -2058,6 +2064,27 @@
         return true;
     }
 
+    /**
+     * When assessing a configuration change, decide if the changes flags and the new configurations
+     * should cause the Activity to relaunch.
+     */
+    private boolean shouldRelaunchLocked(int changes, Configuration newGlobalConfig,
+            Configuration newTaskMergedOverrideConfig) {
+        int configChanged = info.getRealConfigChanged();
+
+        // Override for apps targeting pre-O sdks
+        // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
+        // to the config change.
+        // For O and later, apps will be required to add configChanges="uimode" to their manifest.
+        if (appInfo.targetSdkVersion < O
+                && requestedVrComponent != null
+                && (isInVrUiMode(newGlobalConfig) || isInVrUiMode(newTaskMergedOverrideConfig))) {
+            configChanged |= CONFIG_UI_MODE;
+        }
+
+        return (changes&(~configChanged)) != 0;
+    }
+
     private static int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig,
             Configuration oldTaskOverride) {
         // If we went from full-screen to non-full-screen, make sure to use the correct
@@ -2294,6 +2321,10 @@
         }
     }
 
+    private static boolean isInVrUiMode(Configuration config) {
+        return (config.uiMode & Configuration.UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
+    }
+
     @Override
     public String toString() {
         if (stringName != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ba25120..104fc6a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -544,6 +544,10 @@
         mWindowContainerController.setPictureInPictureAspectRatio(aspectRatio);
     }
 
+    void setPictureInPictureActions(List<RemoteAction> actions) {
+        mWindowContainerController.setPictureInPictureActions(actions);
+    }
+
     void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds, Rect outTempInsetBounds,
             boolean ignoreVisibility) {
         mWindowContainerController.getStackDockedModeBounds(outBounds, outTempBounds,
@@ -554,10 +558,6 @@
         mWindowContainerController.prepareFreezingTaskBounds();
     }
 
-    void setPictureInPictureActions(List<RemoteAction> actions) {
-        mWindowContainerController.setPictureInPictureActions(actions);
-    }
-
     void getWindowContainerBounds(Rect outBounds) {
         if (mWindowContainerController != null) {
             mWindowContainerController.getBounds(outBounds);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index da7dc7d..e954363 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -4913,24 +4913,4 @@
         }
         return topActivityTokens;
     }
-
-    public IBinder getTopVisibleActivity(int uid) {
-        // TODO(b/33197203): get rid of DEFAULT_DISPLAY here?. Used in
-        // VoiceInteractionManagerServiceImpl#showSessionLocked.
-        final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
-        if (display == null) {
-            return null;
-        }
-        final ArrayList<ActivityStack> stacks = display.mStacks;
-        for (int i = stacks.size() - 1; i >= 0; i--) {
-            ActivityStack stack = stacks.get(i);
-            if (stack.getStackVisibilityLocked(null) == ActivityStack.STACK_VISIBLE) {
-                ActivityRecord top = stack.topActivity();
-                if (top != null && stack == mFocusedStack && top.app.uid == uid) {
-                    return top.appToken;
-                }
-            }
-        }
-        return null;
-    }
 }
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 816d5fe..4930c53 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -46,7 +46,7 @@
         implements AudioPlaybackConfiguration.PlayerDeathMonitor, PlayerFocusEnforcer {
 
     public final static String TAG = "AudioService.PlaybackActivityMonitor";
-    private final static boolean DEBUG = true;
+    private final static boolean DEBUG = false;
 
     private ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
     // a public client is one that needs an anonymized version of the playback configurations, we
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 3da49d8..168744b 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -18,9 +18,6 @@
 
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
-import com.android.server.twilight.TwilightListener;
-import com.android.server.twilight.TwilightManager;
-import com.android.server.twilight.TwilightState;
 
 import android.annotation.Nullable;
 import android.hardware.Sensor;
@@ -55,9 +52,6 @@
     // non-zero, which in turn ensures that the total weight is non-zero.
     private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100;
 
-    // Specifies the maximum magnitude of the time of day adjustment.
-    private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1f;
-
     // Debounce for sampling user-initiated changes in display brightness to ensure
     // the user is satisfied with the result before storing the sample.
     private static final int BRIGHTNESS_ADJUSTMENT_SAMPLE_DEBOUNCE_MILLIS = 10000;
@@ -74,9 +68,6 @@
     // The light sensor, or null if not available or needed.
     private final Sensor mLightSensor;
 
-    // The twilight service.
-    private final TwilightManager mTwilight;
-
     // The auto-brightness spline adjustment.
     // The brightness values have been scaled to a range of 0..1.
     private final Spline mScreenAutoBrightnessSpline;
@@ -186,8 +177,6 @@
     private int mBrightnessAdjustmentSampleOldBrightness;
     private float mBrightnessAdjustmentSampleOldGamma;
 
-    private boolean mUseTwilight;
-
     public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
             SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
             int brightnessMin, int brightnessMax, float dozeScaleFactor,
@@ -196,7 +185,6 @@
             int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
             HysteresisLevels dynamicHysteresis) {
         mCallbacks = callbacks;
-        mTwilight = LocalServices.getService(TwilightManager.class);
         mSensorManager = sensorManager;
         mScreenAutoBrightnessSpline = autoBrightnessSpline;
         mScreenBrightnessRangeMinimum = brightnessMin;
@@ -233,7 +221,7 @@
     }
 
     public void configure(boolean enable, float adjustment, boolean dozing,
-            boolean userInitiatedChange, boolean useTwilight) {
+            boolean userInitiatedChange) {
         // While dozing, the application processor may be suspended which will prevent us from
         // receiving new information from the light sensor. On some devices, we may be able to
         // switch to a wake-up light sensor instead but for now we will simply disable the sensor
@@ -242,7 +230,6 @@
         mDozing = dozing;
         boolean changed = setLightSensorEnabled(enable && !dozing);
         changed |= setScreenAutoBrightnessAdjustment(adjustment);
-        changed |= setUseTwilight(useTwilight);
         if (changed) {
             updateAutoBrightness(false /*sendUpdate*/);
         }
@@ -251,17 +238,6 @@
         }
     }
 
-    private boolean setUseTwilight(boolean useTwilight) {
-        if (mUseTwilight == useTwilight) return false;
-        if (useTwilight) {
-            mTwilight.registerListener(mTwilightListener, mHandler);
-        } else {
-            mTwilight.unregisterListener(mTwilightListener);
-        }
-        mUseTwilight = useTwilight;
-        return true;
-    }
-
     public void dump(PrintWriter pw) {
         pw.println();
         pw.println("Automatic Brightness Controller Configuration:");
@@ -276,7 +252,6 @@
         pw.println();
         pw.println("Automatic Brightness Controller State:");
         pw.println("  mLightSensor=" + mLightSensor);
-        pw.println("  mTwilight.getLastTwilightState()=" + mTwilight.getLastTwilightState());
         pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
         pw.println("  mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime));
         pw.println("  mAmbientLux=" + mAmbientLux);
@@ -522,19 +497,6 @@
             }
         }
 
-        if (mUseTwilight) {
-            TwilightState state = mTwilight.getLastTwilightState();
-            if (state != null && state.isNight()) {
-                final long duration = state.sunriseTimeMillis() - state.sunsetTimeMillis();
-                final long progress = System.currentTimeMillis() - state.sunsetTimeMillis();
-                final float amount = (float) Math.pow(2.0 * progress / duration - 1.0, 2.0);
-                gamma *= 1 + amount * TWILIGHT_ADJUSTMENT_MAX_GAMMA;
-                if (DEBUG) {
-                    Slog.d(TAG, "updateAutoBrightness: twilight amount=" + amount);
-                }
-            }
-        }
-
         if (gamma != 1.0f) {
             final float in = value;
             value = MathUtils.pow(value, gamma);
@@ -649,13 +611,6 @@
         }
     };
 
-    private final TwilightListener mTwilightListener = new TwilightListener() {
-        @Override
-        public void onTwilightStateChanged(@Nullable TwilightState state) {
-            updateAutoBrightness(true /*sendUpdate*/);
-        }
-    };
-
     /** Callbacks to request updates to the display's power state. */
     interface Callbacks {
         void updateBrightness();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 015345c..bed269c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -642,7 +642,7 @@
                     && mPowerRequest.brightnessSetByUser;
             mAutomaticBrightnessController.configure(autoBrightnessEnabled,
                     mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,
-                    userInitiatedChange, mPowerRequest.useTwilight);
+                    userInitiatedChange);
         }
 
         // Apply brightness boost.
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index d1f7cfd..e83b228 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -83,6 +83,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -113,6 +114,8 @@
             new ArrayList<>();
     private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
             new CopyOnWriteArrayList<>();
+    private final Map<Integer, Long> mAuthenticatorIds =
+            Collections.synchronizedMap(new HashMap<>());
     private final AppOpsManager mAppOps;
     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
     private static final int MAX_FAILED_ATTEMPTS = 5;
@@ -130,7 +133,6 @@
     private final UserManager mUserManager;
     private ClientMonitor mCurrentClient;
     private ClientMonitor mPendingClient;
-    private long mCurrentAuthenticatorId;
     private PerformanceStats mPerformanceStats;
 
     // Normal fingerprint authentications are tracked by mPerformanceMap.
@@ -239,6 +241,7 @@
 
             if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
             if (mHalDeviceId != 0) {
+                loadAuthenticatorIds();
                 updateActiveGroup(ActivityManager.getCurrentUser(), null);
             } else {
                 Slog.w(TAG, "Failed to open Fingerprint HAL!");
@@ -249,6 +252,26 @@
         return mDaemon;
     }
 
+    /** Populates existing authenticator ids. To be used only during the start of the service. */
+    private void loadAuthenticatorIds() {
+        // This operation can be expensive, so keep track of the elapsed time. Might need to move to
+        // background if it takes too long.
+        long t = System.currentTimeMillis();
+
+        mAuthenticatorIds.clear();
+        for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
+            int userId = getUserOrWorkProfileId(null, user.id);
+            if (!mAuthenticatorIds.containsKey(userId)) {
+                updateActiveGroup(userId, null);
+            }
+        }
+
+        t = System.currentTimeMillis() - t;
+        if (t > 1000) {
+            Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
+        }
+    }
+
     protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
         if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId + ", gid="
                 + groupId + "rem=" + remaining);
@@ -499,14 +522,23 @@
 
     boolean isCurrentUserOrProfile(int userId) {
         UserManager um = UserManager.get(mContext);
-
-        // Allow current user or profiles of the current user...
-        for (int profileId : um.getEnabledProfileIds(mCurrentUserId)) {
-            if (profileId == userId) {
-                return true;
-            }
+        if (um == null) {
+            Slog.e(TAG, "Unable to acquire UserManager");
+            return false;
         }
-        return false;
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            // Allow current user or profiles of the current user...
+            for (int profileId : um.getEnabledProfileIds(mCurrentUserId)) {
+                if (profileId == userId) {
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private boolean isForegroundActivity(int uid, int pid) {
@@ -1195,7 +1227,7 @@
                     daemon.setActiveGroup(userId, fpDir.getAbsolutePath());
                     mCurrentUserId = userId;
                 }
-                mCurrentAuthenticatorId = daemon.getAuthenticatorId();
+                mAuthenticatorIds.put(userId, daemon.getAuthenticatorId());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to setActiveGroup():", e);
             }
@@ -1218,8 +1250,14 @@
      * @return true if this is a work profile
      */
     private boolean isWorkProfile(int userId) {
-        UserInfo info = mUserManager.getUserInfo(userId);
-        return info != null && info.isManagedProfile();
+        UserInfo userInfo = null;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            userInfo = mUserManager.getUserInfo(userId);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        return userInfo != null && userInfo.isManagedProfile();
     }
 
     private void listenForUserSwitches() {
@@ -1239,9 +1277,11 @@
 
     /***
      * @param opPackageName the name of the calling package
-     * @return authenticator id for the current user
+     * @return authenticator id for the calling user
      */
     public long getAuthenticatorId(String opPackageName) {
-        return mCurrentAuthenticatorId;
+        final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId());
+        Long authenticatorId = mAuthenticatorIds.get(userId);
+        return authenticatorId != null ? authenticatorId : 0;
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index ede6e30..10ecb86 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -1123,6 +1123,38 @@
             }
         }
 
+        public void addQueueItem(MediaDescription description) {
+            try {
+                mCb.onAddQueueItem(description);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in addQueueItem.", e);
+            }
+        }
+
+        public void addQueueItemAt(MediaDescription description, int index) {
+            try {
+                mCb.onAddQueueItemAt(description, index);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in addQueueItemAt.", e);
+            }
+        }
+
+        public void removeQueueItem(MediaDescription description) {
+            try {
+                mCb.onRemoveQueueItem(description);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in removeQueueItem.", e);
+            }
+        }
+
+        public void removeQueueItemAt(int index) {
+            try {
+                mCb.onRemoveQueueItemAt(index);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in removeQueueItem.", e);
+            }
+        }
+
         public void adjustVolume(int direction) {
             try {
                 mCb.onAdjustVolume(direction);
@@ -1397,6 +1429,30 @@
         }
 
         @Override
+        public void addQueueItem(MediaDescription description) {
+            updateCallingPackage();
+            mSessionCb.addQueueItem(description);
+        }
+
+        @Override
+        public void addQueueItemAt(MediaDescription description, int index) {
+            updateCallingPackage();
+            mSessionCb.addQueueItemAt(description, index);
+        }
+
+        @Override
+        public void removeQueueItem(MediaDescription description) {
+            updateCallingPackage();
+            mSessionCb.removeQueueItem(description);
+        }
+
+        @Override
+        public void removeQueueItemAt(int index) {
+            updateCallingPackage();
+            mSessionCb.removeQueueItemAt(index);
+        }
+
+        @Override
         public CharSequence getQueueTitle() {
             return mQueueTitle;
         }
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 3bf95ef..98177fe 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -155,10 +155,10 @@
     }
 
     /**
-     * Tells the system UI that volume has changed on a remote session.
+     * Tells the system UI that volume has changed on an active remote session.
      */
     public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
-        if (mRvc == null) {
+        if (mRvc == null || !session.isActive()) {
             return;
         }
         try {
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 279bf90..d6c89a4 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -159,8 +159,7 @@
     }
 
     private boolean isMediaNotification(NotificationRecord record) {
-        return record.getNotification().extras.getParcelable(
-                Notification.EXTRA_MEDIA_SESSION) != null;
+        return record.getNotification().hasMediaSession();
     }
 
     private boolean isCall(NotificationRecord record) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0e5ea6e..4207998 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -833,7 +833,6 @@
     private List<String> mKeepUninstalledPackages;
 
     private UserManagerInternal mUserManagerInternal;
-    private final UserDataPreparer mUserDataPreparer;
 
     private File mCacheDir;
 
@@ -1937,7 +1936,7 @@
 
                     // Clean up any users or apps that were removed or recreated
                     // while this volume was missing
-                    reconcileUsers(volumeUuid);
+                    sUserManager.reconcileUsers(volumeUuid);
                     reconcileApps(volumeUuid);
 
                     // Clean up any install sessions that expired or were
@@ -2161,19 +2160,24 @@
         if (SystemProperties.getInt("ro.cp_system_other_odex", 0) == 1) {
             SystemProperties.set(CP_PREOPT_PROPERTY, "requested");
             // We will wait for up to 100 seconds.
-            final long timeEnd = SystemClock.uptimeMillis() + 100 * 1000;
+            final long timeStart = SystemClock.uptimeMillis();
+            final long timeEnd = timeStart + 100 * 1000;
+            long timeNow = timeStart;
             while (!SystemProperties.get(CP_PREOPT_PROPERTY).equals("finished")) {
                 try {
                     Thread.sleep(WAIT_TIME_MS);
                 } catch (InterruptedException e) {
                     // Do nothing
                 }
-                if (SystemClock.uptimeMillis() > timeEnd) {
+                timeNow = SystemClock.uptimeMillis();
+                if (timeNow > timeEnd) {
                     SystemProperties.set(CP_PREOPT_PROPERTY, "timed-out");
                     Slog.wtf(TAG, "cppreopt did not finish!");
                     break;
                 }
             }
+
+            Slog.i(TAG, "cppreopts took " + (timeNow - timeStart) + " ms");
         }
     }
 
@@ -2265,8 +2269,8 @@
             mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
             mAsecInternalPath = new File(dataDir, "app-asec").getPath();
             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
-            mUserDataPreparer = new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore);
-            sUserManager = new UserManagerService(context, this, mUserDataPreparer, mPackages);
+            sUserManager = new UserManagerService(context, this,
+                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
 
             // Propagate permission configuration in to package manager.
             ArrayMap<String, SystemConfig.PermissionEntry> permConfig
@@ -19966,7 +19970,7 @@
         });
 
         // Now that we're mostly running, clean up stale users and apps
-        reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
+        sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
         reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
     }
 
@@ -21304,60 +21308,6 @@
         }
     }
 
-    /**
-     * Examine all users present on given mounted volume, and destroy data
-     * belonging to users that are no longer valid, or whose user ID has been
-     * recycled.
-     */
-    private void reconcileUsers(String volumeUuid) {
-        final List<File> files = new ArrayList<>();
-        Collections.addAll(files, FileUtils
-                .listFilesOrEmpty(Environment.getDataUserDeDirectory(volumeUuid)));
-        Collections.addAll(files, FileUtils
-                .listFilesOrEmpty(Environment.getDataUserCeDirectory(volumeUuid)));
-        Collections.addAll(files, FileUtils
-                .listFilesOrEmpty(Environment.getDataSystemDeDirectory()));
-        Collections.addAll(files, FileUtils
-                .listFilesOrEmpty(Environment.getDataSystemCeDirectory()));
-        Collections.addAll(files, FileUtils
-                .listFilesOrEmpty(Environment.getDataMiscCeDirectory()));
-        for (File file : files) {
-            if (!file.isDirectory()) continue;
-
-            final int userId;
-            final UserInfo info;
-            try {
-                userId = Integer.parseInt(file.getName());
-                info = sUserManager.getUserInfo(userId);
-            } catch (NumberFormatException e) {
-                Slog.w(TAG, "Invalid user directory " + file);
-                continue;
-            }
-
-            boolean destroyUser = false;
-            if (info == null) {
-                logCriticalInfo(Log.WARN, "Destroying user directory " + file
-                        + " because no matching user was found");
-                destroyUser = true;
-            } else if (!mOnlyCore) {
-                try {
-                    UserManagerService.enforceSerialNumber(file, info.serialNumber);
-                } catch (IOException e) {
-                    logCriticalInfo(Log.WARN, "Destroying user directory " + file
-                            + " because we failed to enforce serial number: " + e);
-                    destroyUser = true;
-                }
-            }
-
-            if (destroyUser) {
-                synchronized (mInstallLock) {
-                    mUserDataPreparer.destroyUserDataLI(volumeUuid, userId,
-                            StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
-                }
-            }
-        }
-    }
-
     private void assertPackageKnown(String volumeUuid, String packageName)
             throws PackageManagerException {
         synchronized (mPackages) {
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 52599fd..fc00acc 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -17,13 +17,28 @@
 package com.android.server.pm;
 
 import android.content.Context;
+import android.content.pm.UserInfo;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 import static com.android.server.pm.PackageManagerService.logCriticalInfo;
 
@@ -31,6 +46,9 @@
  * Helper class for preparing and destroying user storage
  */
 class UserDataPreparer {
+    private static final String TAG = "UserDataPreparer";
+    private static final String XATTR_SERIAL = "user.serial";
+
     private final Object mInstallLock;
     private final Context mContext;
     private final boolean mOnlyCore;
@@ -65,19 +83,15 @@
             storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
 
             if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) {
-                UserManagerService.enforceSerialNumber(
-                        Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial);
+                enforceSerialNumber(getDataUserDeDirectory(volumeUuid, userId), userSerial);
                 if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
-                    UserManagerService.enforceSerialNumber(
-                            Environment.getDataSystemDeDirectory(userId), userSerial);
+                    enforceSerialNumber(getDataSystemDeDirectory(userId), userSerial);
                 }
             }
             if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) {
-                UserManagerService.enforceSerialNumber(
-                        Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial);
+                enforceSerialNumber(getDataUserCeDirectory(volumeUuid, userId), userSerial);
                 if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
-                    UserManagerService.enforceSerialNumber(
-                            Environment.getDataSystemCeDirectory(userId), userSerial);
+                    enforceSerialNumber(getDataSystemCeDirectory(userId), userSerial);
                 }
             }
 
@@ -117,13 +131,13 @@
             // Clean up system data
             if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
                 if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
-                    FileUtils.deleteContentsAndDir(Environment.getUserSystemDirectory(userId));
-                    FileUtils.deleteContentsAndDir(Environment.getDataSystemDeDirectory(userId));
-                    FileUtils.deleteContentsAndDir(Environment.getDataMiscDeDirectory(userId));
+                    FileUtils.deleteContentsAndDir(getUserSystemDirectory(userId));
+                    FileUtils.deleteContentsAndDir(getDataSystemDeDirectory(userId));
+                    FileUtils.deleteContentsAndDir(getDataMiscDeDirectory(userId));
                 }
                 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
-                    FileUtils.deleteContentsAndDir(Environment.getDataSystemCeDirectory(userId));
-                    FileUtils.deleteContentsAndDir(Environment.getDataMiscCeDirectory(userId));
+                    FileUtils.deleteContentsAndDir(getDataSystemCeDirectory(userId));
+                    FileUtils.deleteContentsAndDir(getDataMiscCeDirectory(userId));
                 }
             }
 
@@ -136,4 +150,183 @@
         }
     }
 
+    /**
+     * Examine all users present on given mounted volume, and destroy data
+     * belonging to users that are no longer valid, or whose user ID has been
+     * recycled.
+     */
+    void reconcileUsers(String volumeUuid, List<UserInfo> validUsersList) {
+        final List<File> files = new ArrayList<>();
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataUserDeDirectory(volumeUuid)));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataUserCeDirectory(volumeUuid)));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataSystemDeDirectory()));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataSystemCeDirectory()));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataMiscCeDirectory()));
+        reconcileUsers(volumeUuid, validUsersList, files);
+    }
+
+    @VisibleForTesting
+    void reconcileUsers(String volumeUuid, List<UserInfo> validUsersList, List<File> files) {
+        final int userCount = validUsersList.size();
+        SparseArray<UserInfo> users = new SparseArray<>(userCount);
+        for (int i = 0; i < userCount; i++) {
+            UserInfo user = validUsersList.get(i);
+            users.put(user.id, user);
+        }
+        for (File file : files) {
+            if (!file.isDirectory()) {
+                continue;
+            }
+
+            final int userId;
+            final UserInfo info;
+            try {
+                userId = Integer.parseInt(file.getName());
+                info = users.get(userId);
+            } catch (NumberFormatException e) {
+                Slog.w(TAG, "Invalid user directory " + file);
+                continue;
+            }
+
+            boolean destroyUser = false;
+            if (info == null) {
+                logCriticalInfo(Log.WARN, "Destroying user directory " + file
+                        + " because no matching user was found");
+                destroyUser = true;
+            } else if (!mOnlyCore) {
+                try {
+                    enforceSerialNumber(file, info.serialNumber);
+                } catch (IOException e) {
+                    logCriticalInfo(Log.WARN, "Destroying user directory " + file
+                            + " because we failed to enforce serial number: " + e);
+                    destroyUser = true;
+                }
+            }
+
+            if (destroyUser) {
+                synchronized (mInstallLock) {
+                    destroyUserDataLI(volumeUuid, userId,
+                            StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    protected File getDataMiscCeDirectory(int userId) {
+        return Environment.getDataMiscCeDirectory(userId);
+    }
+
+    @VisibleForTesting
+    protected File getDataSystemCeDirectory(int userId) {
+        return Environment.getDataSystemCeDirectory(userId);
+    }
+
+    @VisibleForTesting
+    protected File getDataMiscDeDirectory(int userId) {
+        return Environment.getDataMiscDeDirectory(userId);
+    }
+
+    @VisibleForTesting
+    protected File getUserSystemDirectory(int userId) {
+        return Environment.getUserSystemDirectory(userId);
+    }
+
+    @VisibleForTesting
+    protected File getDataUserCeDirectory(String volumeUuid, int userId) {
+        return Environment.getDataUserCeDirectory(volumeUuid, userId);
+    }
+
+    @VisibleForTesting
+    protected File getDataSystemDeDirectory(int userId) {
+        return Environment.getDataSystemDeDirectory(userId);
+    }
+
+    @VisibleForTesting
+    protected File getDataUserDeDirectory(String volumeUuid, int userId) {
+        return Environment.getDataUserDeDirectory(volumeUuid, userId);
+    }
+
+    @VisibleForTesting
+    protected boolean isFileEncryptedEmulatedOnly() {
+        return StorageManager.isFileEncryptedEmulatedOnly();
+    }
+
+    /**
+     * Enforce that serial number stored in user directory inode matches the
+     * given expected value. Gracefully sets the serial number if currently
+     * undefined.
+     *
+     * @throws IOException when problem extracting serial number, or serial
+     *             number is mismatched.
+     */
+    void enforceSerialNumber(File file, int serialNumber) throws IOException {
+        if (isFileEncryptedEmulatedOnly()) {
+            // When we're emulating FBE, the directory may have been chmod
+            // 000'ed, meaning we can't read the serial number to enforce it;
+            // instead of destroying the user, just log a warning.
+            Slog.w(TAG, "Device is emulating FBE; assuming current serial number is valid");
+            return;
+        }
+
+        final int foundSerial = getSerialNumber(file);
+        Slog.v(TAG, "Found " + file + " with serial number " + foundSerial);
+
+        if (foundSerial == -1) {
+            Slog.d(TAG, "Serial number missing on " + file + "; assuming current is valid");
+            try {
+                setSerialNumber(file, serialNumber);
+            } catch (IOException e) {
+                Slog.w(TAG, "Failed to set serial number on " + file, e);
+            }
+
+        } else if (foundSerial != serialNumber) {
+            throw new IOException("Found serial number " + foundSerial
+                    + " doesn't match expected " + serialNumber);
+        }
+    }
+
+    /**
+     * Set serial number stored in user directory inode.
+     *
+     * @throws IOException if serial number was already set
+     */
+    private static void setSerialNumber(File file, int serialNumber) throws IOException {
+        try {
+            final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8);
+            Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE);
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    /**
+     * Return serial number stored in user directory inode.
+     *
+     * @return parsed serial number, or -1 if not set
+     */
+    @VisibleForTesting
+    static int getSerialNumber(File file) throws IOException {
+        try {
+            final byte[] buf = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL);
+            final String serial = new String(buf);
+            try {
+                return Integer.parseInt(serial);
+            } catch (NumberFormatException e) {
+                throw new IOException("Bad serial number: " + serial);
+            }
+        } catch (ErrnoException e) {
+            if (e.errno == OsConstants.ENODATA) {
+                return -1;
+            } else {
+                throw e.rethrowAsIOException();
+            }
+        }
+    }
+
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 455d3e4..627fa54 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -218,8 +218,6 @@
     static final int WRITE_USER_MSG = 1;
     static final int WRITE_USER_DELAY = 2*1000;  // 2 seconds
 
-    private static final String XATTR_SERIAL = "user.serial";
-
     // Tron counters
     private static final String TRON_GUEST_CREATED = "users_guest_created";
     private static final String TRON_USER_CREATED = "users_user_created";
@@ -3159,6 +3157,15 @@
     }
 
     /**
+     * Examine all users present on given mounted volume, and destroy data
+     * belonging to users that are no longer valid, or whose user ID has been
+     * recycled.
+     */
+    void reconcileUsers(String volumeUuid) {
+        mUserDataPreparer.reconcileUsers(volumeUuid, getUsers(true /* excludeDying */));
+    }
+
+    /**
      * Make a note of the last started time of a user and do some cleanup.
      * This is called with ActivityManagerService lock held.
      * @param userId the user that was just foregrounded
@@ -3219,78 +3226,6 @@
         return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
     }
 
-    /**
-     * Enforce that serial number stored in user directory inode matches the
-     * given expected value. Gracefully sets the serial number if currently
-     * undefined.
-     *
-     * @throws IOException when problem extracting serial number, or serial
-     *             number is mismatched.
-     */
-    public static void enforceSerialNumber(File file, int serialNumber) throws IOException {
-        if (StorageManager.isFileEncryptedEmulatedOnly()) {
-            // When we're emulating FBE, the directory may have been chmod
-            // 000'ed, meaning we can't read the serial number to enforce it;
-            // instead of destroying the user, just log a warning.
-            Slog.w(LOG_TAG, "Device is emulating FBE; assuming current serial number is valid");
-            return;
-        }
-
-        final int foundSerial = getSerialNumber(file);
-        Slog.v(LOG_TAG, "Found " + file + " with serial number " + foundSerial);
-
-        if (foundSerial == -1) {
-            Slog.d(LOG_TAG, "Serial number missing on " + file + "; assuming current is valid");
-            try {
-                setSerialNumber(file, serialNumber);
-            } catch (IOException e) {
-                Slog.w(LOG_TAG, "Failed to set serial number on " + file, e);
-            }
-
-        } else if (foundSerial != serialNumber) {
-            throw new IOException("Found serial number " + foundSerial
-                    + " doesn't match expected " + serialNumber);
-        }
-    }
-
-    /**
-     * Set serial number stored in user directory inode.
-     *
-     * @throws IOException if serial number was already set
-     */
-    private static void setSerialNumber(File file, int serialNumber)
-            throws IOException {
-        try {
-            final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8);
-            Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE);
-        } catch (ErrnoException e) {
-            throw e.rethrowAsIOException();
-        }
-    }
-
-    /**
-     * Return serial number stored in user directory inode.
-     *
-     * @return parsed serial number, or -1 if not set
-     */
-    private static int getSerialNumber(File file) throws IOException {
-        try {
-            final byte[] buf = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL);
-            final String serial = new String(buf);
-            try {
-                return Integer.parseInt(serial);
-            } catch (NumberFormatException e) {
-                throw new IOException("Bad serial number: " + serial);
-            }
-        } catch (ErrnoException e) {
-            if (e.errno == OsConstants.ENODATA) {
-                return -1;
-            } else {
-                throw e.rethrowAsIOException();
-            }
-        }
-    }
-
     @Override
     public void setSeedAccountData(int userId, String accountName, String accountType,
             PersistableBundle accountOptions, boolean persist) {
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 6edb4d2..7a28081 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -18,6 +18,7 @@
 
 import android.app.StatusBarManager;
 import android.os.Handler;
+import android.os.Message;
 import android.os.SystemClock;
 import android.util.Slog;
 import android.view.View;
@@ -43,6 +44,8 @@
 
     private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
 
+    private static final int MSG_NAV_BAR_VISIBILITY_CHANGED = 1;
+
     protected final String mTag;
     private final int mTransientFlag;
     private final int mUnhideFlag;
@@ -63,6 +66,8 @@
     private boolean mSetUnHideFlagWhenNextTransparent;
     private boolean mNoAnimationOnNextShow;
 
+    private OnBarVisibilityChangedListener mVisibilityChangeListener;
+
     public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
             int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
         mTag = "BarController." + tag;
@@ -72,7 +77,7 @@
         mStatusBarManagerId = statusBarManagerId;
         mTranslucentWmFlag = translucentWmFlag;
         mTransparentFlag = transparentFlag;
-        mHandler = new Handler();
+        mHandler = new BarHandler();
     }
 
     public void setWindow(WindowState win) {
@@ -153,9 +158,18 @@
         mNoAnimationOnNextShow = false;
         final int state = computeStateLw(wasVis, wasAnim, mWin, change);
         final boolean stateChanged = updateStateLw(state);
+
+        if (change && (mVisibilityChangeListener != null)) {
+            mHandler.obtainMessage(MSG_NAV_BAR_VISIBILITY_CHANGED, show ? 1 : 0, 0).sendToTarget();
+        }
+
         return change || stateChanged;
     }
 
+    void setOnBarVisibilityChangedListener(OnBarVisibilityChangedListener listener) {
+        mVisibilityChangeListener = listener;
+    }
+
     protected boolean skipAnimation() {
         return false;
     }
@@ -300,4 +314,22 @@
             pw.println(transientBarStateToString(mTransientBarState));
         }
     }
+
+    private class BarHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_NAV_BAR_VISIBILITY_CHANGED:
+                    final boolean visible = msg.arg1 != 0;
+                    if (mVisibilityChangeListener != null) {
+                        mVisibilityChangeListener.onBarVisibilityChanged(visible);
+                    }
+                    break;
+            }
+        }
+    }
+
+    interface OnBarVisibilityChangedListener {
+        void onBarVisibilityChanged(boolean visible);
+    }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 180f6c9..c795676 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -990,6 +990,14 @@
             WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
             View.NAVIGATION_BAR_TRANSPARENT);
 
+    private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener =
+            new BarController.OnBarVisibilityChangedListener() {
+        @Override
+        public void onBarVisibilityChanged(boolean visible) {
+            mAccessibilityManager.notifyAccessibilityButtonAvailabilityChanged(visible);
+        }
+    };
+
     private ImmersiveModeConfirmation mImmersiveModeConfirmation;
 
     private SystemGesturesPointerEventListener mSystemGestures;
@@ -2900,6 +2908,8 @@
                 }
                 mNavigationBar = win;
                 mNavigationBarController.setWindow(win);
+                mNavigationBarController.setOnBarVisibilityChangedListener(
+                        mNavBarVisibilityListener);
                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                 break;
             case TYPE_NAVIGATION_BAR_PANEL:
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 238866a..91a5f4f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -517,9 +517,6 @@
     private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
             = new ArrayList<PowerManagerInternal.LowPowerModeListener>();
 
-    // True if brightness should be affected by twilight.
-    private boolean mBrightnessUseTwilight;
-
     // True if we are currently in VR Mode.
     private boolean mIsVrModeEnabled;
 
@@ -735,9 +732,6 @@
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.DOUBLE_TAP_TO_WAKE),
                     false, mSettingsObserver, UserHandle.USER_ALL);
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                    Secure.BRIGHTNESS_USE_TWILIGHT),
-                    false, mSettingsObserver, UserHandle.USER_ALL);
             IVrManager vrManager =
                     (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
             if (vrManager != null) {
@@ -878,9 +872,6 @@
                 Settings.System.SCREEN_BRIGHTNESS_MODE,
                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
 
-        mBrightnessUseTwilight = Settings.Secure.getIntForUser(resolver,
-                Secure.BRIGHTNESS_USE_TWILIGHT, 0, UserHandle.USER_CURRENT) != 0;
-
         final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver,
                 Settings.Global.LOW_POWER_MODE, 0) != 0;
         final boolean autoLowPowerModeConfigured = Settings.Global.getInt(resolver,
@@ -2254,7 +2245,6 @@
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
             mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
             mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
-            mDisplayPowerRequest.useTwilight = mBrightnessUseTwilight;
 
             if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                 mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index fb0dd2a..b4467af 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -23,9 +23,6 @@
 
 public interface StatusBarManagerInternal {
     void setNotificationDelegate(NotificationDelegate delegate);
-    void buzzBeepBlinked();
-    void notificationLightPulse(int argb, int onMillis, int offMillis);
-    void notificationLightOff();
     void showScreenPinningRequest(int taskId);
     void showAssistDisclosure();
 
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 7b7db0e..2dfe20a8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -120,40 +120,6 @@
         }
 
         @Override
-        public void buzzBeepBlinked() {
-            if (mBar != null) {
-                try {
-                    mBar.buzzBeepBlinked();
-                } catch (RemoteException ex) {
-                }
-            }
-        }
-
-        @Override
-        public void notificationLightPulse(int argb, int onMillis, int offMillis) {
-            mNotificationLightOn = true;
-            if (mBar != null) {
-                try {
-                    mBar.notificationLightPulse(argb, onMillis, offMillis);
-                } catch (RemoteException ex) {
-                }
-            }
-        }
-
-        @Override
-        public void notificationLightOff() {
-            if (mNotificationLightOn) {
-                mNotificationLightOn = false;
-                if (mBar != null) {
-                    try {
-                        mBar.notificationLightOff();
-                    } catch (RemoteException ex) {
-                    }
-                }
-            }
-        }
-
-        @Override
         public void showScreenPinningRequest(int taskId) {
             if (mBar != null) {
                 try {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 8cc53f0..e026130 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -23,15 +23,12 @@
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.OperationApplicationException;
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -84,12 +81,9 @@
 import com.android.server.IoThread;
 import com.android.server.SystemService;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -241,44 +235,6 @@
                 // the update can be handled in {@link #onSomePackagesChanged}.
                 return true;
             }
-
-            @Override
-            public void onPackageRemoved(String packageName, int uid) {
-                synchronized (mLock) {
-                    UserState userState = getOrCreateUserStateLocked(getChangingUserId());
-                    if (!userState.packageSet.contains(packageName)) {
-                        // Not a TV input package.
-                        return;
-                    }
-                }
-
-                ArrayList<ContentProviderOperation> operations = new ArrayList<>();
-
-                String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?";
-                String[] selectionArgs = { packageName };
-
-                operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI)
-                        .withSelection(selection, selectionArgs).build());
-                operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI)
-                        .withSelection(selection, selectionArgs).build());
-                operations.add(ContentProviderOperation
-                        .newDelete(TvContract.WatchedPrograms.CONTENT_URI)
-                        .withSelection(selection, selectionArgs).build());
-
-                ContentProviderResult[] results = null;
-                try {
-                    ContentResolver cr = getContentResolverForUser(getChangingUserId());
-                    results = cr.applyBatch(TvContract.AUTHORITY, operations);
-                } catch (RemoteException | OperationApplicationException e) {
-                    Slog.e(TAG, "error in applyBatch", e);
-                }
-
-                if (DEBUG) {
-                    Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid
-                            + ")");
-                    Slog.d(TAG, "results=" + results);
-                }
-            }
         };
         monitor.register(mContext, null, UserHandle.ALL, true);
 
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 0fc1900..45b7baf 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -79,4 +79,13 @@
      *       given in {@link android.service.vr.VrModeException} on failure.
      */
     public abstract int hasVrPackage(@NonNull ComponentName packageName, int userId);
+
+    /**
+     * Sets the persistent VR mode state of a device. When a device is in persistent VR mode it will
+     * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
+     * by VR viewers to indicate that a device is placed in a VR viewer.
+     *
+     * @param enabled true if the device should be placed in persistent VR mode.
+     */
+    public abstract void setPersistentVrModeEnabled(boolean enabled);
 }
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 8368b05..51c4ce31 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -20,15 +20,10 @@
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.annotation.NonNull;
-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.FeatureInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Binder;
@@ -53,7 +48,6 @@
 import android.util.SparseArray;
 
 import com.android.internal.R;
-import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.utils.ManagedApplicationService.PendingEvent;
@@ -69,8 +63,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
-import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -121,8 +113,10 @@
     // State protected by mLock
     private boolean mVrModeAllowed;
     private boolean mVrModeEnabled;
+    private boolean mPersistentVrModeEnabled;
     private EnabledComponentsObserver mComponentObserver;
     private ManagedApplicationService mCurrentVrService;
+    private ComponentName mDefaultVrService;
     private Context mContext;
     private ComponentName mCurrentVrModeComponent;
     private int mCurrentVrModeUser;
@@ -157,6 +151,10 @@
             if (mVrModeAllowed) {
                 consumeAndApplyPendingStateLocked();
             } else {
+                // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
+                // exit persistent VR mode when screen is turned off.
+                mPersistentVrModeEnabled = false;
+
                 // Set pending state to current state.
                 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
                     ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
@@ -378,6 +376,12 @@
         }
 
         @Override
+        public void setPersistentVrModeEnabled(boolean enabled) {
+            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
+            VrManagerService.this.setPersistentVrModeEnabled(enabled);
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -387,6 +391,8 @@
             }
             pw.println("********* Dump of VrManagerService *********");
             pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
+            pw.println("Persistent VR mode is currently: " +
+                    ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
             pw.println("Previous state transitions:\n");
             String tab = "  ";
             dumpStateTransitions(pw);
@@ -462,6 +468,11 @@
         public int hasVrPackage(ComponentName packageName, int userId) {
             return VrManagerService.this.hasVrPackage(packageName, userId);
         }
+
+        @Override
+        public void setPersistentVrModeEnabled(boolean enabled) {
+            VrManagerService.this.setPersistentVrModeEnabled(enabled);
+        }
     }
 
     public VrManagerService(Context context) {
@@ -494,6 +505,15 @@
 
                 mComponentObserver.rebuildAll();
             }
+
+            //TODO: something more robust than picking the first one
+            ArraySet<ComponentName> defaultVrComponents =
+                    SystemConfig.getInstance().getDefaultVrComponents();
+            if (defaultVrComponents.size() > 0) {
+                mDefaultVrService = defaultVrComponents.valueAt(0);
+            } else {
+                Slog.i(TAG, "No default vr listener service found.");
+            }
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 mVrModeAllowed = true;
@@ -637,8 +657,8 @@
                 }
             }
 
+            mCurrentVrModeComponent = calling;
             if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
-                mCurrentVrModeComponent = calling;
                 sendUpdatedCaller = true;
             }
 
@@ -947,7 +967,25 @@
             int userId, @NonNull ComponentName callingPackage) {
 
         synchronized (mLock) {
-            VrState pending = new VrState(enabled, targetPackageName, userId, callingPackage);
+            VrState pending;
+            ComponentName targetListener;
+            ComponentName foregroundVrComponent;
+
+            // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
+            // and the system default VR listener is used.
+            boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
+            if (!enabled && mPersistentVrModeEnabled) {
+                targetListener = mDefaultVrService;
+
+                // Current foreground component isn't a VR one (in 2D app case)
+                foregroundVrComponent = null;
+            } else {
+                targetListener = targetPackageName;
+                foregroundVrComponent = callingPackage;
+            }
+            pending = new VrState(
+                    targetEnabledState, targetListener, userId, foregroundVrComponent);
+
             if (!mVrModeAllowed) {
                 // We're not allowed to be in VR mode.  Make this state pending.  This will be
                 // applied the next time we are allowed to enter VR mode unless it is superseded by
@@ -956,7 +994,7 @@
                 return;
             }
 
-            if (!enabled && mCurrentVrService != null) {
+            if (!targetEnabledState && mCurrentVrService != null) {
                 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
                 // and service bind/unbind in case we are immediately switching to another VR app.
                 if (mPendingState == null) {
@@ -971,7 +1009,19 @@
                 mPendingState = null;
             }
 
-            updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
+            updateCurrentVrServiceLocked(
+                    targetEnabledState, targetListener, userId, foregroundVrComponent);
+        }
+    }
+
+    private void setPersistentVrModeEnabled(boolean enabled) {
+        synchronized (mLock) {
+            mPersistentVrModeEnabled = enabled;
+
+            // Disabling persistent mode when not showing a VR should disable the overall vr mode.
+            if (!enabled && mCurrentVrModeComponent == null) {
+                setVrMode(false, null, 0, null);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 596c3d8..a872ea4 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -22,7 +22,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
-import android.animation.ValueAnimator;
 import android.app.RemoteAction;
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
@@ -42,7 +41,6 @@
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
 
-import com.android.internal.policy.PipMotionHelper;
 import com.android.internal.policy.PipSnapAlgorithm;
 import com.android.server.UiThread;
 
@@ -51,7 +49,20 @@
 import java.util.List;
 
 /**
- * Holds the common state of the pinned stack between the system and SystemUI.
+ * Holds the common state of the pinned stack between the system and SystemUI. If SystemUI ever
+ * needs to be restarted, it will be notified with the last known state.
+ *
+ * Changes to the pinned stack also flow through this controller, and generally, the system only
+ * changes the pinned stack bounds through this controller in two ways:
+ *
+ * 1) When first entering PiP: the controller returns the valid bounds given, taking aspect ratio
+ *    and IME state into account.
+ * 2) When rotating the device: the controller calculates the new bounds in the new orientation,
+ *    taking the minimized and IME state into account. In this case, we currently ignore the
+ *    SystemUI adjustments (ie. expanded for menu, interaction, etc).
+ *
+ * Other changes in the system, including adjustment of IME, configuration change, and more are
+ * handled by SystemUI (similar to the docked stack divider).
  */
 class PinnedStackController {
 
@@ -67,18 +78,15 @@
 
     private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback();
     private final PipSnapAlgorithm mSnapAlgorithm;
-    private final PipMotionHelper mMotionHelper;
 
     // States that affect how the PIP can be manipulated
-    private boolean mInInteractiveMode;
     private boolean mIsMinimized;
-    private boolean mIsSnappingToEdge;
     private boolean mIsImeShowing;
     private int mImeHeight;
-    private ValueAnimator mBoundsAnimator = null;
 
-    // The set of actions that are currently allowed on the PiP activity
+    // The set of actions and aspect-ratio for the that are currently allowed on the PiP activity
     private ArrayList<RemoteAction> mActions = new ArrayList<>();
+    private float mAspectRatio = -1f;
 
     // Used to calculate stack bounds across rotations
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -89,6 +97,10 @@
     private Size mDefaultStackSize;
     private Point mScreenEdgeInsets;
 
+    // The aspect ratio bounds of the PIP.
+    private float mMinAspectRatio;
+    private float mMaxAspectRatio;
+
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
     private final Rect mTmpInsets = new Rect();
@@ -100,31 +112,12 @@
     private class PinnedStackControllerCallback extends IPinnedStackController.Stub {
 
         @Override
-        public void setInInteractiveMode(final boolean inInteractiveMode) {
-            mHandler.post(() -> {
-                // Cancel any existing animations on the PIP once the user starts dragging it
-                if (mBoundsAnimator != null && inInteractiveMode) {
-                    mBoundsAnimator.cancel();
-                }
-                mInInteractiveMode = inInteractiveMode;
-            });
-        }
-
-        @Override
         public void setIsMinimized(final boolean isMinimized) {
             mHandler.post(() -> {
                 mIsMinimized = isMinimized;
                 mSnapAlgorithm.setMinimized(isMinimized);
             });
         }
-
-        @Override
-        public void setSnapToEdge(final boolean snapToEdge) {
-            mHandler.post(() -> {
-                mIsSnappingToEdge = snapToEdge;
-                mSnapAlgorithm.setSnapToEdge(snapToEdge);
-            });
-        }
     }
 
     /**
@@ -135,7 +128,6 @@
         @Override
         public void binderDied() {
             // Clean up the state if the listener dies
-            mInInteractiveMode = false;
             mPinnedStackListener = null;
         }
     }
@@ -144,13 +136,13 @@
         mService = service;
         mDisplayContent = displayContent;
         mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
-        mMotionHelper = new PipMotionHelper(UiThread.getHandler());
         mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
         reloadResources();
     }
 
     void onConfigurationChanged() {
         reloadResources();
+        notifyMovementBoundsChanged(false /* fromImeAdjustment */);
     }
 
     /**
@@ -169,6 +161,10 @@
                 dpToPx(defaultSizeDp.getHeight(), mTmpMetrics));
         mScreenEdgeInsets = new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
                 dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
+        mMinAspectRatio = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
+        mMaxAspectRatio = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
     }
 
     /**
@@ -179,20 +175,29 @@
             listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
             listener.onListenerRegistered(mCallbacks);
             mPinnedStackListener = listener;
-            notifyBoundsChanged(mIsImeShowing);
-            notifyMinimizeChanged(mIsMinimized);
-            notifySnapToEdgeChanged(mIsSnappingToEdge);
+            notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
+            // The movement bounds notification needs to be sent before the minimized state, since
+            // SystemUI may use the bounds to retore the minimized position
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
             notifyActionsChanged(mActions);
+            notifyMinimizeChanged(mIsMinimized);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to register pinned stack listener", e);
         }
     }
 
     /**
+     * @return whether the given {@param aspectRatio} is valid.
+     */
+    public boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
+        return mMinAspectRatio <= aspectRatio && aspectRatio <= mMaxAspectRatio;
+    }
+
+    /**
      * Returns the current bounds (or the default bounds if there are no current bounds) with the
      * specified aspect ratio.
      */
-    Rect getAspectRatioBounds(Rect stackBounds, float aspectRatio) {
+    Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio) {
         // Save the snap fraction, calculate the aspect ratio based on the current bounds
         final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
                 getMovementBounds(stackBounds));
@@ -236,27 +241,20 @@
         final Rect movementBounds = new Rect();
         getInsetBounds(movementBounds);
 
-        // Adjust the right/bottom to ensure the stack bounds never goes offscreen
-        movementBounds.right = Math.max(movementBounds.left, movementBounds.right -
-                stackBounds.width());
-        movementBounds.bottom = Math.max(movementBounds.top, movementBounds.bottom -
-                stackBounds.height());
-
         // Apply the movement bounds adjustments based on the current state
-        if (adjustForIme) {
-            if (mIsImeShowing) {
-                movementBounds.bottom -= mImeHeight;
-            }
-        }
+        mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
+                (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
         return movementBounds;
     }
 
     /**
+     * @param preChangeTargetBounds The final bounds of the stack if it is currently animating
      * @return the repositioned PIP bounds given it's pre-change bounds, and the new display
      *         content.
      */
-    Rect onDisplayChanged(Rect preChangeStackBounds, DisplayContent displayContent) {
-        final Rect postChangeStackBounds = new Rect(preChangeStackBounds);
+    Rect onDisplayChanged(Rect preChangeStackBounds, Rect preChangeTargetBounds,
+            DisplayContent displayContent) {
+        final Rect postChangeStackBounds = new Rect(preChangeTargetBounds);
         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         if (!mDisplayInfo.equals(displayInfo)) {
             // Calculate the snap fraction of the current stack along the old movement bounds, and
@@ -277,6 +275,7 @@
                 mSnapAlgorithm.applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds,
                         displaySize, mStableInsets);
             }
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
         }
         return postChangeStackBounds;
     }
@@ -290,42 +289,19 @@
             return;
         }
 
-        final Rect stackBounds = new Rect();
-        mService.getStackBounds(PINNED_STACK_ID, stackBounds);
-        final Rect prevMovementBounds = getMovementBounds(stackBounds);
         mIsImeShowing = adjustedForIme;
         mImeHeight = imeHeight;
-        if (mInInteractiveMode) {
-            // If the user is currently interacting with the PIP and the ime state changes, then
-            // don't adjust the bounds and defer that to after the interaction
-            notifyBoundsChanged(adjustedForIme /* adjustedForIme */);
-        } else {
-            // Otherwise, we can move the PIP to a sane location to ensure that it does not block
-            // the user from interacting with the IME
-            final Rect movementBounds = getMovementBounds(stackBounds);
-            final Rect toBounds = new Rect(stackBounds);
-            if (adjustedForIme) {
-                // IME visible
-                if (stackBounds.top == prevMovementBounds.bottom) {
-                    // If the PIP is resting on top of the IME, then adjust it with the hiding IME
-                    toBounds.offsetTo(toBounds.left, movementBounds.bottom);
-                } else {
-                    toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top));
-                }
-            } else {
-                // IME hidden
-                if (stackBounds.top == prevMovementBounds.bottom) {
-                    // If the PIP is resting on top of the IME, then adjust it with the hiding IME
-                    toBounds.offsetTo(toBounds.left, movementBounds.bottom);
-                }
-            }
-            if (!toBounds.equals(stackBounds)) {
-                if (mBoundsAnimator != null) {
-                    mBoundsAnimator.cancel();
-                }
-                mBoundsAnimator = mMotionHelper.createAnimationToBounds(stackBounds, toBounds);
-                mBoundsAnimator.start();
-            }
+        notifyImeVisibilityChanged(adjustedForIme, imeHeight);
+        notifyMovementBoundsChanged(true /* fromImeAdjustment */);
+    }
+
+    /**
+     * Sets the current aspect ratio.
+     */
+    void setAspectRatio(float aspectRatio) {
+        if (Float.compare(mAspectRatio, aspectRatio) != 0) {
+            mAspectRatio = aspectRatio;
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
         }
     }
 
@@ -341,12 +317,12 @@
     }
 
     /**
-     * Notifies listeners that the PIP movement bounds have changed.
+     * Notifies listeners that the PIP needs to be adjusted for the IME.
      */
-    private void notifyBoundsChanged(boolean adjustedForIme) {
+    private void notifyImeVisibilityChanged(boolean imeVisible, int imeHeight) {
         if (mPinnedStackListener != null) {
             try {
-                mPinnedStackListener.onBoundsChanged(adjustedForIme);
+                mPinnedStackListener.onImeVisibilityChanged(imeVisible, imeHeight);
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
             }
@@ -367,19 +343,6 @@
     }
 
     /**
-     * Notifies listeners that the PIP snap-to-edge state has changed.
-     */
-    private void notifySnapToEdgeChanged(boolean isSnappingToEdge) {
-        if (mPinnedStackListener != null) {
-            try {
-                mPinnedStackListener.onSnapToEdgeStateChanged(isSnappingToEdge);
-            } catch (RemoteException e) {
-                Slog.e(TAG_WM, "Error delivering snap-to-edge changed event.", e);
-            }
-        }
-    }
-
-    /**
      * Notifies listeners that the PIP actions have changed.
      */
     private void notifyActionsChanged(List<RemoteAction> actions) {
@@ -393,6 +356,26 @@
     }
 
     /**
+     * Notifies listeners that the PIP movement bounds have changed.
+     */
+    private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
+        if (mPinnedStackListener != null) {
+            try {
+                Rect insetBounds = new Rect();
+                getInsetBounds(insetBounds);
+                Rect normalBounds = getDefaultBounds();
+                if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
+                    transformBoundsToAspectRatio(normalBounds, mAspectRatio);
+                }
+                mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
+                        fromImeAdjustement);
+            } catch (RemoteException e) {
+                Slog.e(TAG_WM, "Error delivering actions changed event.", e);
+            }
+        }
+    }
+
+    /**
      * @return the bounds on the screen that the PIP can be visible in.
      */
     private void getInsetBounds(Rect outRect) {
@@ -418,7 +401,6 @@
         pw.print(prefix + "  movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
         pw.println();
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
-        pw.println(prefix + "  mInInteractiveMode=" + mInInteractiveMode);
         pw.println(prefix + "  mIsMinimized=" + mIsMinimized);
         if (mActions.isEmpty()) {
             pw.println(prefix + "  mActions=[]");
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index e2ea2c5..36d07e0 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -216,7 +216,28 @@
 
             final int displayId = mContainer.getDisplayContent().getDisplayId();
             final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
-            animateResizePinnedStack(toBounds, -1 /* duration */);
+            final Rect targetBounds = new Rect();
+            mContainer.getAnimatingBounds(targetBounds);
+            if (!toBounds.equals(targetBounds)) {
+                animateResizePinnedStack(toBounds, -1 /* duration */);
+            }
+
+            final PinnedStackController pinnedStackController =
+                    mContainer.getDisplayContent().getPinnedStackController();
+            pinnedStackController.setAspectRatio(
+                    pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+                            ? aspectRatio : -1f);
+        }
+    }
+
+    /** Sets the current picture-in-picture actions. */
+    public void setPictureInPictureActions(List<RemoteAction> actions) {
+        synchronized (mWindowMap) {
+            if (!mService.mSupportsPictureInPicture || mContainer == null) {
+                return;
+            }
+
+            mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
         }
     }
 
@@ -244,17 +265,6 @@
         }
     }
 
-    /** Sets the current picture-in-picture actions. */
-    public void setPictureInPictureActions(List<RemoteAction> actions) {
-        synchronized (mWindowMap) {
-            if (!mService.mSupportsPictureInPicture || mContainer == null) {
-                return;
-            }
-
-            mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
-        }
-    }
-
     private void getRawBounds(Rect outBounds) {
         if (mContainer.getRawFullscreen()) {
             outBounds.setEmpty();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index a1c9c29..544d1e3 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -393,8 +393,10 @@
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         switch (mStackId) {
             case PINNED_STACK_ID:
+                Rect targetBounds = new Rect();
+                getAnimatingBounds(targetBounds);
                 mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds,
-                        mDisplayContent);
+                        targetBounds, mDisplayContent);
                 break;
             case DOCKED_STACK_ID:
                 repositionDockedStackAfterRotation(mTmpRect2);
@@ -670,7 +672,9 @@
 
         // Update the pinned stack controller after the display info is updated
         if (mStackId == PINNED_STACK_ID) {
-            mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds,
+            Rect targetBounds = new Rect();
+            getAnimatingBounds(targetBounds);
+            mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds, targetBounds,
                     mDisplayContent);
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 971794b..597e8b6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2829,36 +2829,6 @@
         mDockedStackCreateBounds = bounds;
     }
 
-    @Override
-    public Rect getPictureInPictureDefaultBounds(int displayId) {
-        synchronized (mWindowMap) {
-            if (!mSupportsPictureInPicture) {
-                return null;
-            }
-
-            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-            return displayContent.getPinnedStackController().getDefaultBounds();
-        }
-    }
-
-    @Override
-    public Rect getPictureInPictureMovementBounds(int displayId) {
-        synchronized (mWindowMap) {
-            if (!mSupportsPictureInPicture) {
-                return null;
-            }
-
-            final Rect stackBounds = new Rect();
-            getStackBounds(PINNED_STACK_ID, stackBounds);
-            if (stackBounds.isEmpty()) {
-                return stackBounds;
-            }
-
-            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-            return displayContent.getPinnedStackController().getMovementBounds(stackBounds);
-        }
-    }
-
     public Rect getPictureInPictureBounds(int displayId, float aspectRatio) {
         synchronized (mWindowMap) {
             if (!mSupportsPictureInPicture) {
@@ -2871,6 +2841,8 @@
                 return null;
             }
 
+            final PinnedStackController pinnedStackController =
+                    displayContent.getPinnedStackController();
             final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID);
             if (stack != null) {
                 // If the stack exists, then use its final bounds to calculate the new aspect ratio
@@ -2879,13 +2851,23 @@
                 stack.getAnimatingBounds(stackBounds);
             } else {
                 // Otherwise, just calculate the aspect ratio bounds from the default bounds
-                stackBounds = displayContent.getPinnedStackController().getDefaultBounds();
+                stackBounds = pinnedStackController.getDefaultBounds();
             }
-            return displayContent.getPinnedStackController().getAspectRatioBounds(stackBounds,
-                    aspectRatio);
+
+            if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
+                return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio);
+            } else {
+                return stackBounds;
+            }
         }
     }
 
+    public boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) {
+        final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+        return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
+                aspectRatio);
+    }
+
     @Override
     public void getStackBounds(int stackId, Rect bounds) {
         synchronized (mWindowMap) {
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index 545b3d7..703518d 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -70,7 +70,7 @@
 static void nativeInit(JNIEnv* env, jobject obj) {
     // TODO(b/31632518)
     if (gThermalModule == nullptr) {
-        gThermalModule = IThermal::getService("thermal");
+        gThermalModule = IThermal::getService();
     }
 
     if (gThermalModule == nullptr) {
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index e46490b..3120af5 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -26,18 +26,11 @@
 
 namespace android {
 
-static int start_sensor_service(void* /*unused*/) {
-    SensorService::instantiate();
-    return 0;
-}
-
 static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
     char propBuf[PROPERTY_VALUE_MAX];
     property_get("system_init.startsensorservice", propBuf, "1");
     if (strcmp(propBuf, "1") == 0) {
-        // Start the sensor service in a new thread
-        createThreadEtc(start_sensor_service, nullptr,
-                        "StartSensorThread", PRIORITY_FOREGROUND);
+        SensorService::instantiate();
     }
 }
 
diff --git a/services/core/jni/com_android_server_location_ContextHubService.cpp b/services/core/jni/com_android_server_location_ContextHubService.cpp
index 517fce0..05ef0d1 100644
--- a/services/core/jni/com_android_server_location_ContextHubService.cpp
+++ b/services/core/jni/com_android_server_location_ContextHubService.cpp
@@ -558,12 +558,12 @@
 void initContextHubService() {
     db.hubInfo.numHubs = 0;
 
-    db.hubInfo.contextHub = IContexthub::getService("context_hub_hal");
+    db.hubInfo.contextHub = IContexthub::getService("context_hub");
 
     if (db.hubInfo.contextHub == nullptr) {
         ALOGE("Could not load context hub hal");
     } else {
-        ALOGI("Loaded context hub hal");
+        ALOGI("Loaded context hub hal, isRemote %s", db.hubInfo.contextHub->isRemote() ? "TRUE" : "FALSE");
     }
 
     // Prep for storing app info
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 578e0b3..003b6d0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -60,6 +60,7 @@
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.IActivityManager;
@@ -6151,8 +6152,12 @@
                 intent.setComponent(mOwners.getDeviceOwnerComponent());
                 intent.setDataAndType(bugreportUri, RemoteBugreportUtils.BUGREPORT_MIMETYPE);
                 intent.putExtra(DeviceAdminReceiver.EXTRA_BUGREPORT_HASH, bugreportHash);
-                mContext.grantUriPermission(mOwners.getDeviceOwnerComponent().getPackageName(),
-                        bugreportUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+                LocalServices.getService(ActivityManagerInternal.class)
+                        .grantUriPermissionFromIntent(Process.SHELL_UID,
+                                mOwners.getDeviceOwnerComponent().getPackageName(),
+                                intent, mOwners.getDeviceOwnerUserId());
                 mContext.sendBroadcastAsUser(intent, UserHandle.of(mOwners.getDeviceOwnerUserId()));
             }
         } catch (FileNotFoundException e) {
@@ -6706,6 +6711,8 @@
         policy.mDelegationMap.clear();
         policy.mStatusBarDisabled = false;
         policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
+        policy.mAffiliationIds.clear();
+        policy.mLockTaskPackages.clear();
         saveSettingsLocked(userId);
 
         try {
@@ -8610,9 +8617,6 @@
         }
     }
 
-    /**
-     * This function returns the list of components allowed to start the task lock mode.
-     */
     @Override
     public String[] getLockTaskPackages(ComponentName who) {
         Preconditions.checkNotNull(who, "ComponentName is null");
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b911d2d..83e209d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -125,8 +125,13 @@
 public final class SystemServer {
     private static final String TAG = "SystemServer";
 
+    // Tag for timing measurement of main thread.
+    private static final String SYSTEM_SERVER_TIMING_TAG = "SystemServerTiming";
+    // Tag for timing measurement of non-main asynchronous operations.
+    private static final String SYSTEM_SERVER_TIMING_ASYNC_TAG = SYSTEM_SERVER_TIMING_TAG + "Async";
+
     private static final BootTimingsTraceLog BOOT_TIMINGS_TRACE_LOG
-            = new BootTimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER);
+            = new BootTimingsTraceLog(SYSTEM_SERVER_TIMING_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
 
     private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
     private static final String ENCRYPTED_STATE = "1";
@@ -149,6 +154,8 @@
             "com.android.server.voiceinteraction.VoiceInteractionManagerService";
     private static final String PRINT_MANAGER_SERVICE_CLASS =
             "com.android.server.print.PrintManagerService";
+    private static final String COMPANION_DEVICE_MANAGER_SERVICE_CLASS =
+            "com.android.server.print.CompanionDeviceManagerService";
     private static final String USB_SERVICE_CLASS =
             "com.android.server.usb.UsbService$Lifecycle";
     private static final String MIDI_SERVICE_CLASS =
@@ -227,8 +234,11 @@
     private boolean mFirstBoot;
     private final boolean mRuntimeRestart;
 
+    private static final String START_SENSOR_SERVICE = "StartSensorService";
+    private Future<?> mSensorServiceStart;
+
     /**
-     * Start the sensor service.
+     * Start the sensor service. This is a blocking call and can take time.
      */
     private static native void startSensorService();
 
@@ -382,7 +392,7 @@
             MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
             final int MAX_UPTIME_MILLIS = 60 * 1000;
             if (uptimeMillis > MAX_UPTIME_MILLIS) {
-                Slog.wtf("SystemServerTiming",
+                Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                         "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
             }
         }
@@ -584,9 +594,15 @@
 
         // The sensor service needs access to package manager service, app ops
         // service, and permissions service, therefore we start it after them.
-        traceBeginAndSlog("StartSensorService");
-        startSensorService();
-        traceEnd();
+        // Start sensor service in a separate thread. Completion should be checked
+        // before using it.
+        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
+            BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
+                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+            traceLog.traceBegin(START_SENSOR_SERVICE);
+            startSensorService();
+            traceLog.traceEnd();
+        }, START_SENSOR_SERVICE);
     }
 
     /**
@@ -742,6 +758,9 @@
             traceEnd();
 
             traceBeginAndSlog("StartWindowManagerService");
+            // WMS needs sensor service ready
+            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
+            mSensorServiceStart = null;
             wm = WindowManagerService.main(context, inputManager,
                     mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                     !mFirstBoot, mOnlyCore, new PhoneWindowManager());
@@ -1333,6 +1352,10 @@
                 traceEnd();
             }
 
+            traceBeginAndSlog("StartCompanionDeviceManager");
+            mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
+            traceEnd();
+
             traceBeginAndSlog("StartRestrictionManager");
             mSystemServiceManager.startService(RestrictionsManagerService.class);
             traceEnd();
@@ -1590,7 +1613,7 @@
                 webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
                     Slog.i(TAG, WEBVIEW_PREPARATION);
                     BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
-                            "SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER);
+                            SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
                     traceLog.traceBegin(WEBVIEW_PREPARATION);
                     mWebViewUpdateService.prepareWebViewInSystemServer();
                     traceLog.traceEnd();
@@ -1651,13 +1674,13 @@
             Watchdog.getInstance().start();
             traceEnd();
 
-            if (webviewPrep != null) {
-                ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
-            }
-
             // It is now okay to let the various system services start their
             // third party code...
             traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
+            // confirm webview completion before starting 3rd party
+            if (webviewPrep != null) {
+                ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
+            }
             mSystemServiceManager.startBootPhase(
                     SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
             traceEnd();
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
new file mode 100644
index 0000000..9824c1d
--- /dev/null
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.server.print;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.app.PendingIntent;
+import android.companion.AssociationRequest;
+import android.companion.ICompanionDeviceManager;
+import android.companion.ICompanionDeviceManagerService;
+import android.companion.IOnAssociateCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.server.SystemService;
+
+//TODO move to own package!
+/** @hide */
+public class CompanionDeviceManagerService extends SystemService {
+
+    private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
+            "com.android.companiondevicemanager", ".DeviceDiscoveryService");
+
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "CompanionDeviceManagerService";
+
+    private final CompanionDeviceManagerImpl mImpl;
+
+    public CompanionDeviceManagerService(Context context) {
+        super(context);
+        mImpl = new CompanionDeviceManagerImpl();
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.COMPANION_DEVICE_SERVICE, mImpl);
+    }
+
+    class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
+
+        @Override
+        public void associate(
+                AssociationRequest request,
+                IOnAssociateCallback callback,
+                String callingPackage) throws RemoteException {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
+                        + ", callingPackage = " + callingPackage + ")");
+            }
+            checkNotNull(request);
+            checkNotNull(callback);
+            final long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                //TODO bindServiceAsUser
+                getContext().bindService(
+                        new Intent().setComponent(SERVICE_TO_BIND_TO),
+                        getServiceConnection(request, callback, callingPackage),
+                        Context.BIND_AUTO_CREATE);
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+    }
+
+    private ServiceConnection getServiceConnection(
+            final AssociationRequest<?> request,
+            final IOnAssociateCallback callback,
+            final String callingPackage) {
+        return new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                if (DEBUG) {
+                    Log.i(LOG_TAG,
+                            "onServiceConnected(name = " + name + ", service = "
+                                    + service + ")");
+                }
+                try {
+                    ICompanionDeviceManagerService.Stub
+                            .asInterface(service)
+                            .startDiscovery(
+                                    request,
+                                    getCallback(callingPackage, callback),
+                                    callingPackage);
+                } catch (RemoteException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                if (DEBUG) Log.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
+            }
+        };
+    }
+
+    private IOnAssociateCallback.Stub getCallback(
+            String callingPackage,
+            IOnAssociateCallback propagateTo) {
+        return new IOnAssociateCallback.Stub() {
+
+            @Override
+            public void onSuccess(PendingIntent launcher)
+                    throws RemoteException {
+                if (DEBUG) Log.i(LOG_TAG, "onSuccess(launcher = " + launcher + ")");
+                recordSpecialPriviledgesForPackage(callingPackage);
+                propagateTo.onSuccess(launcher);
+            }
+
+            @Override
+            public void onFailure(CharSequence reason) throws RemoteException {
+                if (DEBUG) Log.i(LOG_TAG, "onFailure()");
+                propagateTo.onFailure(reason);
+            }
+        };
+    }
+
+    void recordSpecialPriviledgesForPackage(String priviledgedPackage) {
+        //TODO Show dialog before recording notification access
+//        final SettingStringHelper setting =
+//                new SettingStringHelper(
+//                        getContext().getContentResolver(),
+//                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+//                        Binder.getCallingUid());
+//        setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
+    }
+}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index f30c466..f943ee2c 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -541,6 +541,8 @@
     }
 
     private void stopDemoMode() {
+        mDeviceInDemoMode = false;
+        mIsCarrierDemoMode = false;
         mPreloadAppsInstaller = null;
         mCameraIdsWithFlash = null;
         mInjector.destroyWakeLock();
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index aa08b41..064ab0a 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -112,6 +112,7 @@
         Notification n2 = new Notification.Builder(mContext)
                 .setCategory(Notification.CATEGORY_CALL)
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+                .setColorized(true /* colorized */)
                 .build();
         mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
                 callPkg, 1, "highcall", callUid, callUid, n2,
@@ -186,10 +187,10 @@
         final List<NotificationRecord> expected = new ArrayList<>();
         expected.add(mRecordHighCall);
         expected.add(mRecordDefaultMedia);
-        expected.add(mRecordStarredContact);
-        expected.add(mRecordContact);
         expected.add(mRecordInlineReply);
         expected.add(mRecordSms);
+        expected.add(mRecordStarredContact);
+        expected.add(mRecordContact);
         expected.add(mRecordEmail);
         expected.add(mRecordUrgent);
         expected.add(mRecordCheater);
@@ -207,14 +208,19 @@
     @Test
     public void testMessaging() throws Exception {
         NotificationComparator comp = new NotificationComparator(mContext);
-        assertTrue(comp.isImportantMessaging(mRecordStarredContact));
-        assertTrue(comp.isImportantMessaging(mRecordContact));
         assertTrue(comp.isImportantMessaging(mRecordInlineReply));
         assertTrue(comp.isImportantMessaging(mRecordSms));
         assertFalse(comp.isImportantMessaging(mRecordEmail));
         assertFalse(comp.isImportantMessaging(mRecordCheater));
     }
 
+    @Test
+    public void testPeople() throws Exception {
+        NotificationComparator comp = new NotificationComparator(mContext);
+        assertTrue(comp.isImportantPeople(mRecordStarredContact));
+        assertTrue(comp.isImportantPeople(mRecordContact));
+    }
+
     private NotificationChannel getDefaultChannel() {
         return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
                 NotificationManager.IMPORTANCE_LOW);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 9645916..3f34d4f 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -76,6 +76,7 @@
 import android.net.INetworkPolicyListener;
 import android.net.INetworkStatsService;
 import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkPolicy;
@@ -975,7 +976,8 @@
         info.setDetailedState(DetailedState.CONNECTED, null, null);
         final LinkProperties prop = new LinkProperties();
         prop.setInterfaceName(TEST_IFACE);
-        return new NetworkState(info, prop, null, null, null, TEST_SSID);
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+        return new NetworkState(info, prop, networkCapabilities, null, null, TEST_SSID);
     }
 
     private void expectCurrentTime() throws Exception {
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 7df638c..6fb65d5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2089,9 +2089,19 @@
         assertTrue(dpm.getAffiliationIds(admin2).isEmpty());
         assertFalse(dpm.isAffiliatedUser());
 
+        // Set affiliation ids again, then clear PO to check that the user becomes unaffiliated
+        dpm.setAffiliationIds(admin2, userAffiliationIds);
+        assertTrue(dpm.isAffiliatedUser());
+        dpm.clearProfileOwner(admin2);
+        assertFalse(dpm.isAffiliatedUser());
+
         // Check that the system user remains affiliated.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         assertTrue(dpm.isAffiliatedUser());
+
+        // Clear the device owner - the user becomes unaffiliated.
+        clearDeviceOwner();
+        assertFalse(dpm.isAffiliatedUser());
     }
 
     public void testGetUserProvisioningState_defaultResult() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
new file mode 100644
index 0000000..7a676e25
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserDataPreparerTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.pm;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.FileUtils;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * <p>Run with:<pre>
+ * m FrameworksServicesTests &&
+ * adb install \
+ * -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
+ * adb shell am instrument -e class com.android.server.pm.UserDataPreparerTest \
+ * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * </pre>
+ */
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+@SmallTest
+public class UserDataPreparerTest {
+
+    private static final int TEST_USER_SERIAL = 1000;
+    private static final int TEST_USER_ID = 10;
+
+    private TestUserDataPreparer mUserDataPreparer;
+
+    @Mock
+    private StorageManager mStorageManagerMock;
+
+    @Mock
+    private Context mContextMock;
+
+    @Mock
+    private Installer mInstaller;
+
+    private Object mInstallLock;
+
+    @Before
+    public void setup() {
+        Context ctx = InstrumentationRegistry.getContext();
+        FileUtils.deleteContents(ctx.getCacheDir());
+        mInstallLock = new Object();
+        MockitoAnnotations.initMocks(this);
+        mUserDataPreparer = new TestUserDataPreparer(mInstaller, mInstallLock, mContextMock, false,
+                ctx.getCacheDir());
+        when(mContextMock.getSystemServiceName(StorageManager.class))
+                .thenReturn(Context.STORAGE_SERVICE);
+        when(mContextMock.getSystemService(eq(Context.STORAGE_SERVICE)))
+                .thenReturn(mStorageManagerMock);
+        VolumeInfo testVolume = new VolumeInfo("testuuid", VolumeInfo.TYPE_PRIVATE, null, null);
+        when(mStorageManagerMock.getWritablePrivateVolumes()).thenReturn(Arrays.asList(testVolume));
+    }
+
+    @Test
+    public void testPrepareUserData_De() throws Exception {
+        File userDeDir = mUserDataPreparer.getDataUserDeDirectory(null, TEST_USER_ID);
+        userDeDir.mkdirs();
+        File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
+        systemDeDir.mkdirs();
+        mUserDataPreparer
+                .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_DE);
+        verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
+                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
+        verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
+                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
+        int serialNumber = UserDataPreparer.getSerialNumber(userDeDir);
+        assertEquals(TEST_USER_SERIAL, serialNumber);
+        serialNumber = UserDataPreparer.getSerialNumber(systemDeDir);
+        assertEquals(TEST_USER_SERIAL, serialNumber);
+    }
+
+    @Test
+    public void testPrepareUserData_Ce() throws Exception {
+        File userCeDir = mUserDataPreparer.getDataUserCeDirectory(null, TEST_USER_ID);
+        userCeDir.mkdirs();
+        File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
+        systemCeDir.mkdirs();
+        mUserDataPreparer
+                .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_CE);
+        verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
+                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
+        verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
+                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
+        int serialNumber = UserDataPreparer.getSerialNumber(userCeDir);
+        assertEquals(TEST_USER_SERIAL, serialNumber);
+        serialNumber = UserDataPreparer.getSerialNumber(systemCeDir);
+        assertEquals(TEST_USER_SERIAL, serialNumber);
+    }
+
+    @Test
+    public void testDestroyUserData() throws Exception {
+        // Add file in CE
+        File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
+        systemCeDir.mkdirs();
+        File ceFile = new File(systemCeDir, "file");
+        writeFile(ceFile, "-----" );
+        testDestroyUserData_De();
+        // CE directory should be preserved
+        assertEquals(Collections.singletonList(ceFile), Arrays.asList(FileUtils.listFilesOrEmpty(
+                systemCeDir)));
+
+        testDestroyUserData_Ce();
+
+        // Verify that testDir is empty
+        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+                mUserDataPreparer.testDir)));
+    }
+
+    @Test
+    public void testDestroyUserData_De() throws Exception {
+        File systemDir = mUserDataPreparer.getUserSystemDirectory(TEST_USER_ID);
+        systemDir.mkdirs();
+        writeFile(new File(systemDir, "file"), "-----" );
+        File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
+        systemDeDir.mkdirs();
+        writeFile(new File(systemDeDir, "file"), "-----" );
+        File miscDeDir = mUserDataPreparer.getDataMiscDeDirectory(TEST_USER_ID);
+        miscDeDir.mkdirs();
+        writeFile(new File(miscDeDir, "file"), "-----" );
+
+        mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_DE);
+
+        verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
+                        eq(StorageManager.FLAG_STORAGE_DE));
+        verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
+                        eq(StorageManager.FLAG_STORAGE_DE));
+
+        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(systemDir)));
+        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+                systemDeDir)));
+        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+                miscDeDir)));
+    }
+
+    @Test
+    public void testDestroyUserData_Ce() throws Exception {
+        File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
+        systemCeDir.mkdirs();
+        writeFile(new File(systemCeDir, "file"), "-----" );
+        File miscCeDir = mUserDataPreparer.getDataMiscCeDirectory(TEST_USER_ID);
+        miscCeDir.mkdirs();
+        writeFile(new File(miscCeDir, "file"), "-----" );
+
+        mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_CE);
+
+        verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
+                eq(StorageManager.FLAG_STORAGE_CE));
+        verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
+                eq(StorageManager.FLAG_STORAGE_CE));
+
+        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+                systemCeDir)));
+        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
+                miscCeDir)));
+    }
+
+    @Test
+    public void testReconcileUsers() throws Exception {
+        UserInfo u1 = new UserInfo(1, "u1", 0);
+        UserInfo u2 = new UserInfo(2, "u2", 0);
+        File testDir = mUserDataPreparer.testDir;
+        File dir1 = new File(testDir, "1");
+        dir1.mkdirs();
+        File dir2 = new File(testDir, "2");
+        dir2.mkdirs();
+        File dir3 = new File(testDir, "3");
+        dir3.mkdirs();
+
+        mUserDataPreparer
+                .reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL, Arrays.asList(u1, u2),
+                        Arrays.asList(dir1, dir2, dir3));
+        // Verify that user 3 data is removed
+        verify(mInstaller).destroyUserData(isNull(String.class), eq(3),
+                eq(StorageManager.FLAG_STORAGE_DE|StorageManager.FLAG_STORAGE_CE));
+    }
+
+    private static void writeFile(File file, String content) throws IOException {
+        try (FileOutputStream os = new FileOutputStream(file)) {
+            os.write(content.getBytes(Charset.defaultCharset()));
+        }
+    }
+
+    private static class TestUserDataPreparer extends UserDataPreparer {
+        File testDir;
+
+        TestUserDataPreparer(Installer installer, Object installLock, Context context,
+                boolean onlyCore, File testDir) {
+            super(installer, installLock, context, onlyCore);
+            this.testDir = testDir;
+        }
+
+        @Override
+        protected File getDataMiscCeDirectory(int userId) {
+            return new File(testDir, "misc_ce_" + userId);
+        }
+
+        @Override
+        protected File getDataSystemCeDirectory(int userId) {
+            return new File(testDir, "system_ce_" + userId);
+        }
+
+        @Override
+        protected File getDataMiscDeDirectory(int userId) {
+            return new File(testDir, "misc_de_" + userId);
+        }
+
+        @Override
+        protected File getUserSystemDirectory(int userId) {
+            return new File(testDir, "user_system_" + userId);
+        }
+
+        @Override
+        protected File getDataUserCeDirectory(String volumeUuid, int userId) {
+            return new File(testDir, "user_ce_" + userId);
+        }
+
+        @Override
+        protected File getDataSystemDeDirectory(int userId) {
+            return new File(testDir, "system_de_" + userId);
+        }
+
+        @Override
+        protected File getDataUserDeDirectory(String volumeUuid, int userId) {
+            return new File(testDir, "user_de_" + userId);
+        }
+
+        @Override
+        protected boolean isFileEncryptedEmulatedOnly() {
+            return false;
+        }
+    }
+
+}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index d0ccd55..6e10029 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -98,6 +98,7 @@
     private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
     private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
     private static final String SESSION_CREATE_CONN = "CS.crCo";
+    private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
     private static final String SESSION_ABORT = "CS.ab";
     private static final String SESSION_ANSWER = "CS.an";
     private static final String SESSION_ANSWER_VIDEO = "CS.anV";
@@ -142,6 +143,7 @@
     private static final int MSG_PULL_EXTERNAL_CALL = 22;
     private static final int MSG_SEND_CALL_EVENT = 23;
     private static final int MSG_ON_EXTRAS_CHANGED = 24;
+    private static final int MSG_CREATE_CONNECTION_FAILED = 25;
 
     private static Connection sNullConnection;
 
@@ -211,6 +213,25 @@
         }
 
         @Override
+        public void createConnectionFailed(
+                String callId,
+                ConnectionRequest request,
+                boolean isIncoming,
+                Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_CREATE_CONN_FAILED);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = request;
+                args.arg3 = Log.createSubsession();
+                args.argi1 = isIncoming ? 1 : 0;
+                mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void abort(String callId, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_ABORT);
             try {
@@ -552,6 +573,35 @@
                     }
                     break;
                 }
+                case MSG_CREATE_CONNECTION_FAILED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession((Session) args.arg3, SESSION_HANDLER +
+                            SESSION_CREATE_CONN_FAILED);
+                    try {
+                        final String id = (String) args.arg1;
+                        final ConnectionRequest request = (ConnectionRequest) args.arg2;
+                        final boolean isIncoming = args.argi1 == 1;
+                        if (!mAreAccountsInitialized) {
+                            Log.d(this, "Enqueueing pre-init request %s", id);
+                            mPreInitializationConnectionRequests.add(
+                                    new android.telecom.Logging.Runnable(
+                                            SESSION_HANDLER + SESSION_CREATE_CONN_FAILED + ".pICR",
+                                            null /*lock*/) {
+                                        @Override
+                                        public void loggedRun() {
+                                            createConnectionFailed(id, request, isIncoming);
+                                        }
+                                    }.prepare());
+                        } else {
+                            Log.i(this, "createConnectionFailed %s", id);
+                            createConnectionFailed(id, request, isIncoming);
+                        }
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 case MSG_ABORT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_ABORT);
@@ -1175,6 +1225,17 @@
         }
     }
 
+    private void createConnectionFailed(final String callId, final ConnectionRequest request,
+            boolean isIncoming) {
+
+        Log.i(this, "createConnectionFailed %s", callId);
+        if (isIncoming) {
+            onCreateIncomingConnectionFailed(request);
+        } else {
+            onCreateOutgoingConnectionFailed(request);
+        }
+    }
+
     private void abort(String callId) {
         Log.d(this, "abort %s", callId);
         findConnectionForAction(callId, "abort").onAbort();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index ba7b6a1..96070b8 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1517,6 +1517,10 @@
      *      otherwise.
      */
     public boolean isIncomingCallPermitted(PhoneAccountHandle phoneAccountHandle) {
+        if (phoneAccountHandle == null) {
+            return false;
+        }
+
         ITelecomService service = getTelecomService();
         if (service != null) {
             try {
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 8a27675..20feba7 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -46,6 +46,9 @@
             boolean isUnknown,
             in Session.Info sessionInfo);
 
+    void createConnectionFailed(String callId, in ConnectionRequest request, boolean isIncoming,
+            in Session.Info sessionInfo);
+
     void abort(String callId, in Session.Info sessionInfo);
 
     void answerVideo(String callId, int videoState, in Session.Info sessionInfo);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
index 6629770..251bf24 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
@@ -30,8 +30,9 @@
 import android.transition.AutoTransition;
 import android.transition.ChangeBounds;
 import android.transition.Transition;
-import android.transition.TransitionSet;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
+import android.transition.TransitionSet;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -84,7 +85,7 @@
         fadeIn.setDuration(50);
         noFadeIn.addTransition(new Fade(Fade.OUT)).addTransition(new ChangeBounds()).addTransition(fadeIn);
 
-        myTransition.addListener(new Transition.TransitionListenerAdapter() {
+        myTransition.addListener(new TransitionListenerAdapter() {
             @Override
             public void onTransitionStart(Transition transition) {
                 System.out.println("---------ListView Tops: Before--------");
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index 76792ce..3d7bd94 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -86,8 +86,7 @@
     if (path.find("res/") == 0 && referenced_resources.find(path) == referenced_resources.end()) {
       if (context->IsVerbose()) {
         context->GetDiagnostics()->Note(DiagMessage()
-                                        << "Resource '" << path << "' not referenced in "
-                                        << "resource table; removing from APK.");
+                                        << "Removing resource '" << path << "' from APK.");
       }
       continue;
     }
@@ -110,8 +109,8 @@
     }
 
     std::unique_ptr<io::IData> data = file->OpenAsData();
-    // TODO(lecesne): Only compress the files that were compressed in the original APK.
-    if (!writer->StartEntry(path, ArchiveEntry::kCompress) ||
+    uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
+    if (!writer->StartEntry(path, compression_flags) ||
         !writer->WriteEntry(data->data(), data->size()) || !writer->FinishEntry()) {
       context->GetDiagnostics()->Error(DiagMessage()
                                        << "Error when writing file '" << path << "' in APK.");
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 3ed698b..227ffa3 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
 static const char* sMajorVersion = "2";
 
 // Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "5";
+static const char* sMinorVersion = "6";
 
 int PrintVersion() {
   std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index fdabce1..35971e7 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -39,6 +39,8 @@
       return "bool";
     case ResourceType::kColor:
       return "color";
+    case ResourceType::kConfigVarying:
+      return "configVarying";
     case ResourceType::kDimen:
       return "dimen";
     case ResourceType::kDrawable:
@@ -85,6 +87,7 @@
     {"^attr-private", ResourceType::kAttrPrivate},
     {"bool", ResourceType::kBool},
     {"color", ResourceType::kColor},
+    {"configVarying", ResourceType::kConfigVarying},
     {"dimen", ResourceType::kDimen},
     {"drawable", ResourceType::kDrawable},
     {"font", ResourceType::kFont},
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 1950ea3..4d915d9 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -44,6 +44,11 @@
   kAttrPrivate,
   kBool,
   kColor,
+
+  // Not really a type, but it shows up in some CTS tests and
+  // we need to continue respecting it.
+  kConfigVarying,
+
   kDimen,
   kDrawable,
   kFont,
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 79379fe..1c750c6 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -338,50 +338,52 @@
   using BagParseFunc = std::function<bool(ResourceParser*, xml::XmlPullParser*,
                                           ParsedResource*)>;
 
-  static const auto elToItemMap =
-      ImmutableMap<std::string, ItemTypeFormat>::CreatePreSorted({
-          {"bool", {ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN}},
-          {"color", {ResourceType::kColor, android::ResTable_map::TYPE_COLOR}},
-          {"dimen",
-           {ResourceType::kDimen, android::ResTable_map::TYPE_FLOAT |
-                                      android::ResTable_map::TYPE_FRACTION |
-                                      android::ResTable_map::TYPE_DIMENSION}},
-          {"drawable",
-           {ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR}},
-          {"fraction",
-           {ResourceType::kFraction,
-            android::ResTable_map::TYPE_FLOAT |
-                android::ResTable_map::TYPE_FRACTION |
-                android::ResTable_map::TYPE_DIMENSION}},
-          {"integer",
-           {ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER}},
-          {"string",
-           {ResourceType::kString, android::ResTable_map::TYPE_STRING}},
-      });
+  static const auto elToItemMap = ImmutableMap<std::string, ItemTypeFormat>::CreatePreSorted({
+      {"bool", {ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN}},
+      {"color", {ResourceType::kColor, android::ResTable_map::TYPE_COLOR}},
+      {"configVarying", {ResourceType::kConfigVarying, android::ResTable_map::TYPE_ANY}},
+      {"dimen",
+       {ResourceType::kDimen,
+        android::ResTable_map::TYPE_FLOAT | android::ResTable_map::TYPE_FRACTION |
+            android::ResTable_map::TYPE_DIMENSION}},
+      {"drawable", {ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR}},
+      {"fraction",
+       {ResourceType::kFraction,
+        android::ResTable_map::TYPE_FLOAT | android::ResTable_map::TYPE_FRACTION |
+            android::ResTable_map::TYPE_DIMENSION}},
+      {"integer", {ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER}},
+      {"string", {ResourceType::kString, android::ResTable_map::TYPE_STRING}},
+  });
 
-  static const auto elToBagMap =
-      ImmutableMap<std::string, BagParseFunc>::CreatePreSorted({
-          {"add-resource", std::mem_fn(&ResourceParser::ParseAddResource)},
-          {"array", std::mem_fn(&ResourceParser::ParseArray)},
-          {"attr", std::mem_fn(&ResourceParser::ParseAttr)},
-          {"declare-styleable",
-           std::mem_fn(&ResourceParser::ParseDeclareStyleable)},
-          {"integer-array", std::mem_fn(&ResourceParser::ParseIntegerArray)},
-          {"java-symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
-          {"plurals", std::mem_fn(&ResourceParser::ParsePlural)},
-          {"public", std::mem_fn(&ResourceParser::ParsePublic)},
-          {"public-group", std::mem_fn(&ResourceParser::ParsePublicGroup)},
-          {"string-array", std::mem_fn(&ResourceParser::ParseStringArray)},
-          {"style", std::mem_fn(&ResourceParser::ParseStyle)},
-          {"symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
-      });
+  static const auto elToBagMap = ImmutableMap<std::string, BagParseFunc>::CreatePreSorted({
+      {"add-resource", std::mem_fn(&ResourceParser::ParseAddResource)},
+      {"array", std::mem_fn(&ResourceParser::ParseArray)},
+      {"attr", std::mem_fn(&ResourceParser::ParseAttr)},
+      {"configVarying",
+       std::bind(&ResourceParser::ParseStyle, std::placeholders::_1, ResourceType::kConfigVarying,
+                 std::placeholders::_2, std::placeholders::_3)},
+      {"declare-styleable", std::mem_fn(&ResourceParser::ParseDeclareStyleable)},
+      {"integer-array", std::mem_fn(&ResourceParser::ParseIntegerArray)},
+      {"java-symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
+      {"plurals", std::mem_fn(&ResourceParser::ParsePlural)},
+      {"public", std::mem_fn(&ResourceParser::ParsePublic)},
+      {"public-group", std::mem_fn(&ResourceParser::ParsePublicGroup)},
+      {"string-array", std::mem_fn(&ResourceParser::ParseStringArray)},
+      {"style", std::bind(&ResourceParser::ParseStyle, std::placeholders::_1, ResourceType::kStyle,
+                          std::placeholders::_2, std::placeholders::_3)},
+      {"symbol", std::mem_fn(&ResourceParser::ParseSymbol)},
+  });
 
   std::string resource_type = parser->element_name();
 
   // The value format accepted for this resource.
   uint32_t resource_format = 0u;
 
+  bool can_be_item = true;
+  bool can_be_bag = true;
   if (resource_type == "item") {
+    can_be_bag = false;
+
     // Items have their type encoded in the type attribute.
     if (Maybe<StringPiece> maybe_type =
             xml::FindNonEmptyAttribute(parser, "type")) {
@@ -406,6 +408,17 @@
         return false;
       }
     }
+  } else if (resource_type == "bag") {
+    can_be_item = false;
+
+    // Bags have their type encoded in the type attribute.
+    if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
+      resource_type = maybe_type.value().to_string();
+    } else {
+      diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
+                   << "<bag> must have a 'type' attribute");
+      return false;
+    }
   }
 
   // Get the name of the resource. This will be checked later, because not all
@@ -426,36 +439,61 @@
     return true;
   }
 
-  const auto item_iter = elToItemMap.find(resource_type);
-  if (item_iter != elToItemMap.end()) {
-    // This is an item, record its type and format and start parsing.
+  if (can_be_item) {
+    const auto item_iter = elToItemMap.find(resource_type);
+    if (item_iter != elToItemMap.end()) {
+      // This is an item, record its type and format and start parsing.
 
-    if (!maybe_name) {
-      diag_->Error(DiagMessage(out_resource->source)
-                   << "<" << parser->element_name()
-                   << "> missing 'name' attribute");
-      return false;
+      if (!maybe_name) {
+        diag_->Error(DiagMessage(out_resource->source)
+                     << "<" << parser->element_name() << "> missing 'name' attribute");
+        return false;
+      }
+
+      out_resource->name.type = item_iter->second.type;
+      out_resource->name.entry = maybe_name.value().to_string();
+
+      // Only use the implicit format for this type if it wasn't overridden.
+      if (!resource_format) {
+        resource_format = item_iter->second.format;
+      }
+
+      if (!ParseItem(parser, out_resource, resource_format)) {
+        return false;
+      }
+      return true;
     }
-
-    out_resource->name.type = item_iter->second.type;
-    out_resource->name.entry = maybe_name.value().to_string();
-
-    // Only use the implicit format for this type if it wasn't overridden.
-    if (!resource_format) {
-      resource_format = item_iter->second.format;
-    }
-
-    if (!ParseItem(parser, out_resource, resource_format)) {
-      return false;
-    }
-    return true;
   }
 
   // This might be a bag or something.
-  const auto bag_iter = elToBagMap.find(resource_type);
-  if (bag_iter != elToBagMap.end()) {
-    // Ensure we have a name (unless this is a <public-group>).
-    if (resource_type != "public-group") {
+  if (can_be_bag) {
+    const auto bag_iter = elToBagMap.find(resource_type);
+    if (bag_iter != elToBagMap.end()) {
+      // Ensure we have a name (unless this is a <public-group>).
+      if (resource_type != "public-group") {
+        if (!maybe_name) {
+          diag_->Error(DiagMessage(out_resource->source)
+                       << "<" << parser->element_name() << "> missing 'name' attribute");
+          return false;
+        }
+
+        out_resource->name.entry = maybe_name.value().to_string();
+      }
+
+      // Call the associated parse method. The type will be filled in by the
+      // parse func.
+      if (!bag_iter->second(this, parser, out_resource)) {
+        return false;
+      }
+      return true;
+    }
+  }
+
+  if (can_be_item) {
+    // Try parsing the elementName (or type) as a resource. These shall only be
+    // resources like 'layout' or 'xml' and they can only be references.
+    const ResourceType* parsed_type = ParseResourceType(resource_type);
+    if (parsed_type) {
       if (!maybe_name) {
         diag_->Error(DiagMessage(out_resource->source)
                      << "<" << parser->element_name()
@@ -463,39 +501,16 @@
         return false;
       }
 
+      out_resource->name.type = *parsed_type;
       out_resource->name.entry = maybe_name.value().to_string();
+      out_resource->value = ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
+      if (!out_resource->value) {
+        diag_->Error(DiagMessage(out_resource->source)
+                     << "invalid value for type '" << *parsed_type << "'. Expected a reference");
+        return false;
+      }
+      return true;
     }
-
-    // Call the associated parse method. The type will be filled in by the
-    // parse func.
-    if (!bag_iter->second(this, parser, out_resource)) {
-      return false;
-    }
-    return true;
-  }
-
-  // Try parsing the elementName (or type) as a resource. These shall only be
-  // resources like 'layout' or 'xml' and they can only be references.
-  const ResourceType* parsed_type = ParseResourceType(resource_type);
-  if (parsed_type) {
-    if (!maybe_name) {
-      diag_->Error(DiagMessage(out_resource->source)
-                   << "<" << parser->element_name()
-                   << "> missing 'name' attribute");
-      return false;
-    }
-
-    out_resource->name.type = *parsed_type;
-    out_resource->name.entry = maybe_name.value().to_string();
-    out_resource->value =
-        ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
-    if (!out_resource->value) {
-      diag_->Error(DiagMessage(out_resource->source)
-                   << "invalid value for type '" << *parsed_type
-                   << "'. Expected a reference");
-      return false;
-    }
-    return true;
   }
 
   diag_->Warn(DiagMessage(out_resource->source)
@@ -1048,9 +1063,9 @@
   return true;
 }
 
-bool ResourceParser::ParseStyle(xml::XmlPullParser* parser,
+bool ResourceParser::ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
                                 ParsedResource* out_resource) {
-  out_resource->name.type = ResourceType::kStyle;
+  out_resource->name.type = type;
 
   std::unique_ptr<Style> style = util::make_unique<Style>();
 
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index c12dacf..cc0fa26 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -102,7 +102,8 @@
                      bool weak);
   Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
                                                const android::StringPiece& tag);
-  bool ParseStyle(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
+                  ParsedResource* out_resource);
   bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
   bool ParseDeclareStyleable(xml::XmlPullParser* parser,
                              ParsedResource* out_resource);
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 5762fb0..cf901da 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -719,4 +719,23 @@
   EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType);
 }
 
+TEST_F(ResourceParserTest, ParseConfigVaryingItem) {
+  std::string input = R"EOF(<item name="foo" type="configVarying">Hey</item>)EOF";
+  ASSERT_TRUE(TestParse(input));
+  ASSERT_NE(nullptr, test::GetValue<String>(&table_, "configVarying/foo"));
+}
+
+TEST_F(ResourceParserTest, ParseBagElement) {
+  std::string input =
+      R"EOF(<bag name="bag" type="configVarying"><item name="test">Hello!</item></bag>)EOF";
+  ASSERT_TRUE(TestParse(input));
+
+  Style* val = test::GetValue<Style>(&table_, "configVarying/bag");
+  ASSERT_NE(nullptr, val);
+
+  ASSERT_EQ(1u, val->entries.size());
+  EXPECT_EQ(Reference(test::ParseNameOrDie("attr/test")), val->entries[0].key);
+  EXPECT_NE(nullptr, ValueCast<RawString>(val->entries[0].value.get()));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
index 6acb4d3..ad4e3ce 100644
--- a/tools/aapt2/Resource_test.cpp
+++ b/tools/aapt2/Resource_test.cpp
@@ -49,6 +49,10 @@
   ASSERT_NE(type, nullptr);
   EXPECT_EQ(*type, ResourceType::kColor);
 
+  type = ParseResourceType("configVarying");
+  ASSERT_NE(type, nullptr);
+  EXPECT_EQ(*type, ResourceType::kConfigVarying);
+
   type = ParseResourceType("dimen");
   ASSERT_NE(type, nullptr);
   EXPECT_EQ(*type, ResourceType::kDimen);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index e5eaf2f..b4cf4f8 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -111,6 +111,36 @@
   return true;
 }
 
+// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
+static bool VerifyUsesFeature(xml::Element* el, SourcePathDiagnostics* diag) {
+  bool has_name = false;
+  if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
+    if (attr->value.empty()) {
+      diag->Error(DiagMessage(el->line_number)
+                  << "android:name in <uses-feature> must not be empty");
+      return false;
+    }
+    has_name = true;
+  }
+
+  bool has_gl_es_version = false;
+  if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
+    if (has_name) {
+      diag->Error(DiagMessage(el->line_number)
+                  << "cannot define both android:name and android:glEsVersion in <uses-feature>");
+      return false;
+    }
+    has_gl_es_version = true;
+  }
+
+  if (!has_name && !has_gl_es_version) {
+    diag->Error(DiagMessage(el->line_number)
+                << "<uses-feature> must have either android:name or android:glEsVersion attribute");
+    return false;
+  }
+  return true;
+}
+
 bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
                                IDiagnostics* diag) {
   // First verify some options.
@@ -134,15 +164,25 @@
     }
   }
 
-  // Common intent-filter actions.
+  // Common <intent-filter> actions.
   xml::XmlNodeAction intent_filter_action;
   intent_filter_action["action"];
   intent_filter_action["category"];
   intent_filter_action["data"];
 
-  // Common meta-data actions.
+  // Common <meta-data> actions.
   xml::XmlNodeAction meta_data_action;
 
+  // Common <uses-feature> actions.
+  xml::XmlNodeAction uses_feature_action;
+  uses_feature_action.Action(VerifyUsesFeature);
+
+  // Common component actions.
+  xml::XmlNodeAction component_action;
+  component_action.Action(RequiredNameIsJavaClassName);
+  component_action["intent-filter"] = intent_filter_action;
+  component_action["meta-data"] = meta_data_action;
+
   // Manifest actions.
   xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
   manifest_action.Action(VerifyManifest);
@@ -190,6 +230,7 @@
   });
 
   // Instrumentation actions.
+  manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
   manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
     if (!options_.rename_instrumentation_target_package) {
       return true;
@@ -201,6 +242,7 @@
     }
     return true;
   });
+  manifest_action["instrumentation"]["meta-data"] = meta_data_action;
 
   manifest_action["original-package"];
   manifest_action["protected-broadcast"];
@@ -208,51 +250,28 @@
   manifest_action["permission"];
   manifest_action["permission-tree"];
   manifest_action["permission-group"];
-
   manifest_action["uses-configuration"];
-  manifest_action["uses-feature"];
   manifest_action["supports-screens"];
-
+  manifest_action["uses-feature"] = uses_feature_action;
+  manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
   manifest_action["compatible-screens"];
   manifest_action["compatible-screens"]["screen"];
-
   manifest_action["supports-gl-texture"];
-
   manifest_action["meta-data"] = meta_data_action;
 
   // Application actions.
   xml::XmlNodeAction& application_action = manifest_action["application"];
   application_action.Action(OptionalNameIsJavaClassName);
 
-  // Uses library actions.
   application_action["uses-library"];
-
-  // Meta-data.
   application_action["meta-data"] = meta_data_action;
-
-  // Activity actions.
-  application_action["activity"].Action(RequiredNameIsJavaClassName);
-  application_action["activity"]["intent-filter"] = intent_filter_action;
-  application_action["activity"]["meta-data"] = meta_data_action;
-
-  // Activity alias actions.
-  application_action["activity-alias"]["intent-filter"] = intent_filter_action;
-  application_action["activity-alias"]["meta-data"] = meta_data_action;
-
-  // Service actions.
-  application_action["service"].Action(RequiredNameIsJavaClassName);
-  application_action["service"]["intent-filter"] = intent_filter_action;
-  application_action["service"]["meta-data"] = meta_data_action;
-
-  // Receiver actions.
-  application_action["receiver"].Action(RequiredNameIsJavaClassName);
-  application_action["receiver"]["intent-filter"] = intent_filter_action;
-  application_action["receiver"]["meta-data"] = meta_data_action;
+  application_action["activity"] = component_action;
+  application_action["activity-alias"] = component_action;
+  application_action["service"] = component_action;
+  application_action["receiver"] = component_action;
 
   // Provider actions.
-  application_action["provider"].Action(RequiredNameIsJavaClassName);
-  application_action["provider"]["intent-filter"] = intent_filter_action;
-  application_action["provider"]["meta-data"] = meta_data_action;
+  application_action["provider"] = component_action;
   application_action["provider"]["grant-uri-permissions"];
   application_action["provider"]["path-permissions"];
 
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 12a304a..ce84993 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -90,7 +90,7 @@
 }
 
 TEST_F(ManifestFixerTest, AllowMetaData) {
-    auto doc = Verify(R"EOF(
+  auto doc = Verify(R"EOF(
         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                   package="android">
           <meta-data />
@@ -98,12 +98,13 @@
             <meta-data />
             <activity android:name=".Hi"><meta-data /></activity>
             <activity-alias android:name=".Ho"><meta-data /></activity-alias>
-            <receiver android:name=".OffToWork"><meta-data /></receiver>
-            <provider android:name=".We"><meta-data /></provider>
-            <service android:name=".Go"><meta-data /></service>
+            <receiver android:name=".OffTo"><meta-data /></receiver>
+            <provider android:name=".Work"><meta-data /></provider>
+            <service android:name=".We"><meta-data /></service>
           </application>
+          <instrumentation android:name=".Go"><meta-data /></instrumentation>
         </manifest>)EOF");
-    ASSERT_NE(nullptr, doc);
+  ASSERT_NE(nullptr, doc);
 }
 
 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
@@ -290,7 +291,7 @@
   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
-        <instrumentation android:targetPackage="android" />
+        <instrumentation android:name=".TestRunner" android:targetPackage="android" />
       </manifest>)EOF",
                                                             options);
   ASSERT_NE(nullptr, doc);
@@ -354,4 +355,51 @@
   EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(attr->compiled_value.get()));
 }
 
+TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
+  std::string input = R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android">
+          <uses-feature android:name="feature" />
+          <uses-feature android:glEsVersion="1" />
+          <feature-group />
+          <feature-group>
+            <uses-feature android:name="feature_in_group" />
+            <uses-feature android:glEsVersion="2" />
+          </feature-group>
+        </manifest>)EOF";
+  EXPECT_NE(nullptr, Verify(input));
+
+  input = R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android">
+          <uses-feature android:name="feature" android:glEsVersion="1" />
+        </manifest>)EOF";
+  EXPECT_EQ(nullptr, Verify(input));
+
+  input = R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android">
+          <uses-feature />
+        </manifest>)EOF";
+  EXPECT_EQ(nullptr, Verify(input));
+
+  input = R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android">
+          <feature-group>
+            <uses-feature android:name="feature" android:glEsVersion="1" />
+          </feature-group>
+        </manifest>)EOF";
+  EXPECT_EQ(nullptr, Verify(input));
+
+  input = R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android">
+          <feature-group>
+            <uses-feature />
+          </feature-group>
+        </manifest>)EOF";
+  EXPECT_EQ(nullptr, Verify(input));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index e2a752e..44d22c4 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,12 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.6
+### `aapt2`
+- Support legacy `configVarying` resource type.
+- Support `<bag>` tag and treat as `<style>` regardless of type.
+- Add `<feature-group>` manifest tag verification.
+- Add `<meta-data>` tag support to `<instrumentation>`.
+
 ## Version 2.5
 ### `aapt2 link ...`
 - Transition XML versioning: Adds a new flag `--no-version-transitions` to disable automatic
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 56898f1..253ea6f 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -483,16 +483,6 @@
     }
 
     @Override
-    public Rect getPictureInPictureDefaultBounds(int displayId) {
-        return null;
-    }
-
-    @Override
-    public Rect getPictureInPictureMovementBounds(int displayId)  {
-        return null;
-    }
-
-    @Override
     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha)
             throws RemoteException {
     }