Merge "Adding API for apps to specify their aspect ratio when entering PIP."
diff --git a/Android.mk b/Android.mk
index 6f96803..bd04214 100644
--- a/Android.mk
+++ b/Android.mk
@@ -251,6 +251,8 @@
 	core/java/android/os/storage/IObbActionListener.aidl \
 	core/java/android/security/IKeystoreService.aidl \
 	core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
+	core/java/android/service/autofill/IAutoFillManagerService.aidl \
+	core/java/android/service/autofill/IAutoFillService.aidl \
 	core/java/android/service/carrier/ICarrierService.aidl \
 	core/java/android/service/carrier/ICarrierMessagingCallback.aidl \
 	core/java/android/service/carrier/ICarrierMessagingService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 413d8b0..a72cbb08 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18,6 +18,7 @@
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+    field public static final java.lang.String BIND_AUTO_FILL = "android.permission.BIND_AUTO_FILL";
     field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
@@ -28,6 +29,7 @@
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -34634,6 +34636,20 @@
 
 }
 
+package android.service.autofill {
+
+  public abstract class AutoFillService extends android.app.Service {
+    ctor public AutoFillService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onNewSession(java.lang.String, android.os.Bundle, int, android.app.assist.AssistStructure);
+    method public void onReady();
+    method public void onSessionFinished(java.lang.String);
+    method public void onShutdown();
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+  }
+
+}
+
 package android.service.carrier {
 
   public class CarrierIdentifier implements android.os.Parcelable {
@@ -34836,6 +34852,21 @@
 
 package android.service.notification {
 
+  public final class Adjustment implements android.os.Parcelable {
+    ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+    ctor protected Adjustment(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.CharSequence getExplanation();
+    method public int getImportance();
+    method public java.lang.String getKey();
+    method public java.lang.String getPackage();
+    method public android.net.Uri getReference();
+    method public android.os.Bundle getSignals();
+    method public int getUser();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+  }
+
   public final class Condition implements android.os.Parcelable {
     ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
@@ -34882,6 +34913,15 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustNotification(android.service.notification.Adjustment);
+    method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -34903,6 +34943,7 @@
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
+    method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, int);
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
     method public static void requestRebind(android.content.ComponentName);
@@ -34917,6 +34958,25 @@
     field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
+    field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
+    field public static final int REASON_SNOOZED = 18; // 0x12
+    field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+    field public static final int REASON_USER_SWITCH = 19; // 0x13
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
     field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
     field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
@@ -34943,7 +35003,7 @@
   }
 
   public class StatusBarNotification implements android.os.Parcelable {
-    ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
+    ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
     ctor public StatusBarNotification(android.os.Parcel);
     method public android.service.notification.StatusBarNotification clone();
     method public int describeContents();
@@ -34951,6 +35011,7 @@
     method public int getId();
     method public java.lang.String getKey();
     method public android.app.Notification getNotification();
+    method public android.app.NotificationChannel getNotificationChannel();
     method public java.lang.String getOverrideGroupKey();
     method public java.lang.String getPackageName();
     method public long getPostTime();
@@ -37536,6 +37597,7 @@
 
   public class TelephonyManager {
     method public boolean canChangeDtmfToneLength();
+    method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telephony.TelephonyManager createForSubscriptionId(int);
     method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method public int getCallState();
@@ -37558,6 +37620,7 @@
     method public int getNetworkType();
     method public int getPhoneCount();
     method public int getPhoneType();
+    method public android.telephony.ServiceState getServiceState();
     method public java.lang.String getSimCountryIso();
     method public java.lang.String getSimOperator();
     method public java.lang.String getSimOperatorName();
diff --git a/api/system-current.txt b/api/system-current.txt
index e1f568f..401e5a8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -28,6 +28,7 @@
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+    field public static final java.lang.String BIND_AUTO_FILL = "android.permission.BIND_AUTO_FILL";
     field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
@@ -41,6 +42,7 @@
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_RECOMMENDATION_SERVICE = "android.permission.BIND_PRINT_RECOMMENDATION_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
@@ -130,6 +132,7 @@
     field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
     field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
+    field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
     field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
     field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
@@ -4550,7 +4553,9 @@
     ctor public EphemeralResolverService();
     method public final void attachBaseContext(android.content.Context);
     method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
+    method public abstract deprecated java.util.List<android.content.pm.EphemeralResolveInfo> onEphemeralResolveInfoList(int[], int);
+    method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralIntentFilter(int[]);
+    method public java.util.List<android.content.pm.EphemeralResolveInfo> onGetEphemeralResolveInfo(int[]);
     field public static final java.lang.String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
     field public static final java.lang.String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
   }
@@ -9194,6 +9199,7 @@
     field public static final java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT";
     field public static final java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME";
     field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
+    field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
     field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
     field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
     field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
@@ -9898,18 +9904,39 @@
     field public int reqTouchScreen;
   }
 
+  public final class EphemeralIntentFilter implements android.os.Parcelable {
+    ctor public EphemeralIntentFilter(java.lang.String, java.util.List<android.content.IntentFilter>);
+    method public int describeContents();
+    method public java.util.List<android.content.IntentFilter> getFilters();
+    method public java.lang.String getSplitName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralIntentFilter> CREATOR;
+  }
+
   public final class EphemeralResolveInfo implements android.os.Parcelable {
-    ctor public EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
+    ctor public deprecated EphemeralResolveInfo(android.net.Uri, java.lang.String, java.util.List<android.content.IntentFilter>);
+    ctor public EphemeralResolveInfo(android.content.pm.EphemeralResolveInfo.EphemeralDigest, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
+    ctor public EphemeralResolveInfo(java.lang.String, java.lang.String, java.util.List<android.content.pm.EphemeralIntentFilter>);
     method public int describeContents();
     method public byte[] getDigestBytes();
     method public int getDigestPrefix();
-    method public java.util.List<android.content.IntentFilter> getFilters();
+    method public deprecated java.util.List<android.content.IntentFilter> getFilters();
+    method public java.util.List<android.content.pm.EphemeralIntentFilter> getIntentFilters();
     method public java.lang.String getPackageName();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo> CREATOR;
     field public static final java.lang.String SHA_ALGORITHM = "SHA-256";
   }
 
+  public static final class EphemeralResolveInfo.EphemeralDigest implements android.os.Parcelable {
+    ctor public EphemeralResolveInfo.EphemeralDigest(java.lang.String);
+    method public int describeContents();
+    method public byte[][] getDigestBytes();
+    method public int[] getDigestPrefix();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.EphemeralResolveInfo.EphemeralDigest> CREATOR;
+  }
+
   public final class FeatureGroupInfo implements android.os.Parcelable {
     ctor public FeatureGroupInfo();
     ctor public FeatureGroupInfo(android.content.pm.FeatureGroupInfo);
@@ -37402,6 +37429,20 @@
 
 }
 
+package android.service.autofill {
+
+  public abstract class AutoFillService extends android.app.Service {
+    ctor public AutoFillService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onNewSession(java.lang.String, android.os.Bundle, int, android.app.assist.AssistStructure);
+    method public void onReady();
+    method public void onSessionFinished(java.lang.String);
+    method public void onShutdown();
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+  }
+
+}
+
 package android.service.carrier {
 
   public class CarrierIdentifier implements android.os.Parcelable {
@@ -37665,6 +37706,15 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustNotification(android.service.notification.Adjustment);
+    method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -37688,6 +37738,7 @@
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
+    method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, int);
     method public void registerAsSystemService(android.content.Context, android.content.ComponentName, int) throws android.os.RemoteException;
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
@@ -37705,6 +37756,25 @@
     field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
+    field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
+    field public static final int REASON_SNOOZED = 18; // 0x12
+    field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+    field public static final int REASON_USER_SWITCH = 19; // 0x13
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
     field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
     field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
@@ -37732,39 +37802,8 @@
     field public static final android.os.Parcelable.Creator<android.service.notification.NotificationListenerService.RankingMap> CREATOR;
   }
 
-  public abstract class NotificationRankerService extends android.service.notification.NotificationListenerService {
-    ctor public NotificationRankerService();
-    method public final void adjustNotification(android.service.notification.Adjustment);
-    method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method public void onNotificationActionClick(java.lang.String, long, int);
-    method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
-    method public void onNotificationRemoved(java.lang.String, long, int);
-    method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
-    field public static final int REASON_APP_CANCEL = 8; // 0x8
-    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
-    field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
-    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
-    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
-    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
-    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
-    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
-    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
-    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
-    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
-    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
-    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
-    field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
-    field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
-    field public static final int REASON_SNOOZED = 18; // 0x12
-    field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
-    field public static final int REASON_USER_STOPPED = 6; // 0x6
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationRankerService";
-  }
-
   public class StatusBarNotification implements android.os.Parcelable {
-    ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
+    ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
     ctor public StatusBarNotification(android.os.Parcel);
     method public android.service.notification.StatusBarNotification clone();
     method public int describeContents();
@@ -37772,6 +37811,7 @@
     method public int getId();
     method public java.lang.String getKey();
     method public android.app.Notification getNotification();
+    method public android.app.NotificationChannel getNotificationChannel();
     method public java.lang.String getOverrideGroupKey();
     method public java.lang.String getPackageName();
     method public long getPostTime();
@@ -40659,6 +40699,7 @@
     method public boolean canChangeDtmfToneLength();
     method public int checkCarrierPrivilegesForPackage(java.lang.String);
     method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
+    method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telephony.TelephonyManager createForSubscriptionId(int);
     method public void dial(java.lang.String);
     method public boolean disableDataConnectivity();
@@ -40696,6 +40737,7 @@
     method public int getNetworkType();
     method public int getPhoneCount();
     method public int getPhoneType();
+    method public android.telephony.ServiceState getServiceState();
     method public java.lang.String getSimCountryIso();
     method public java.lang.String getSimOperator();
     method public java.lang.String getSimOperatorName();
diff --git a/api/test-current.txt b/api/test-current.txt
index 870c224..aeeb4b3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -18,6 +18,7 @@
     field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
     field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
     field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+    field public static final java.lang.String BIND_AUTO_FILL = "android.permission.BIND_AUTO_FILL";
     field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
@@ -28,6 +29,7 @@
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
     field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+    field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -32770,6 +32772,7 @@
     field public static final java.lang.String ALLOWED_GEOLOCATION_ORIGINS = "allowed_geolocation_origins";
     field public static final deprecated java.lang.String ALLOW_MOCK_LOCATION = "mock_location";
     field public static final java.lang.String ANDROID_ID = "android_id";
+    field public static final java.lang.String AUTO_FILL_SERVICE = "auto_fill_service";
     field public static final deprecated java.lang.String BACKGROUND_DATA = "background_data";
     field public static final deprecated java.lang.String BLUETOOTH_ON = "bluetooth_on";
     field public static final android.net.Uri CONTENT_URI;
@@ -34723,6 +34726,20 @@
 
 }
 
+package android.service.autofill {
+
+  public abstract class AutoFillService extends android.app.Service {
+    ctor public AutoFillService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onNewSession(java.lang.String, android.os.Bundle, int, android.app.assist.AssistStructure);
+    method public void onReady();
+    method public void onSessionFinished(java.lang.String);
+    method public void onShutdown();
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+  }
+
+}
+
 package android.service.carrier {
 
   public class CarrierIdentifier implements android.os.Parcelable {
@@ -34925,6 +34942,21 @@
 
 package android.service.notification {
 
+  public final class Adjustment implements android.os.Parcelable {
+    ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri, int);
+    ctor protected Adjustment(android.os.Parcel);
+    method public int describeContents();
+    method public java.lang.CharSequence getExplanation();
+    method public int getImportance();
+    method public java.lang.String getKey();
+    method public java.lang.String getPackage();
+    method public android.net.Uri getReference();
+    method public android.os.Bundle getSignals();
+    method public int getUser();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+  }
+
   public final class Condition implements android.os.Parcelable {
     ctor public Condition(android.net.Uri, java.lang.String, int);
     ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
@@ -34971,6 +35003,15 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+    ctor public NotificationAssistantService();
+    method public final void adjustNotification(android.service.notification.Adjustment);
+    method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -34992,6 +35033,7 @@
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
+    method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, int);
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
     method public static void requestRebind(android.content.ComponentName);
@@ -35006,6 +35048,25 @@
     field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
     field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
     field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+    field public static final int REASON_APP_CANCEL = 8; // 0x8
+    field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+    field public static final int REASON_CHANNEL_BANNED = 17; // 0x11
+    field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+    field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+    field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+    field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+    field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+    field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+    field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+    field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+    field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+    field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 14; // 0xe
+    field public static final int REASON_PROFILE_TURNED_OFF = 15; // 0xf
+    field public static final int REASON_SNOOZED = 18; // 0x12
+    field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
+    field public static final int REASON_USER_STOPPED = 6; // 0x6
+    field public static final int REASON_USER_SWITCH = 19; // 0x13
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
     field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
     field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
@@ -35032,7 +35093,7 @@
   }
 
   public class StatusBarNotification implements android.os.Parcelable {
-    ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
+    ctor public deprecated StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
     ctor public StatusBarNotification(android.os.Parcel);
     method public android.service.notification.StatusBarNotification clone();
     method public int describeContents();
@@ -35040,6 +35101,7 @@
     method public int getId();
     method public java.lang.String getKey();
     method public android.app.Notification getNotification();
+    method public android.app.NotificationChannel getNotificationChannel();
     method public java.lang.String getOverrideGroupKey();
     method public java.lang.String getPackageName();
     method public long getPostTime();
@@ -37625,6 +37687,7 @@
 
   public class TelephonyManager {
     method public boolean canChangeDtmfToneLength();
+    method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telephony.TelephonyManager createForSubscriptionId(int);
     method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method public int getCallState();
@@ -37647,6 +37710,7 @@
     method public int getNetworkType();
     method public int getPhoneCount();
     method public int getPhoneType();
+    method public android.telephony.ServiceState getServiceState();
     method public java.lang.String getSimCountryIso();
     method public java.lang.String getSimOperator();
     method public java.lang.String getSimOperatorName();
diff --git a/cmds/locksettings/Android.mk b/cmds/locksettings/Android.mk
new file mode 100644
index 0000000..76766c7
--- /dev/null
+++ b/cmds/locksettings/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_MODULE := locksettings
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := locksettings
+LOCAL_SRC_FILES := locksettings
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_PREBUILT)
+
+
diff --git a/cmds/locksettings/locksettings b/cmds/locksettings/locksettings
new file mode 100755
index 0000000..c963b23
--- /dev/null
+++ b/cmds/locksettings/locksettings
@@ -0,0 +1,5 @@
+# Script to start "locksettings" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/locksettings.jar
+exec app_process $base/bin com.android.commands.locksettings.LockSettingsCmd "$@"
diff --git a/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
new file mode 100644
index 0000000..1e426d6
--- /dev/null
+++ b/cmds/locksettings/src/com/android/commands/locksettings/LockSettingsCmd.java
@@ -0,0 +1,65 @@
+/*
+ * 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.commands.locksettings;
+
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.os.ShellCallback;
+
+import com.android.internal.os.BaseCommand;
+import com.android.internal.widget.ILockSettings;
+
+import java.io.FileDescriptor;
+import java.io.PrintStream;
+
+public final class LockSettingsCmd extends BaseCommand {
+
+    private static final String USAGE =
+            "usage: locksettings set-pattern [--old OLD_CREDENTIAL] NEW_PATTERN\n" +
+            "       locksettings set-pin [--old OLD_CREDENTIAL] NEW_PIN\n" +
+            "       locksettings set-password [--old OLD_CREDENTIAL] NEW_PASSWORD\n" +
+            "       locksettings clear [--old OLD_CREDENTIAL]\n" +
+            "\n" +
+            "locksettings set-pattern: sets a pattern\n" +
+            "    A pattern is specified by a non-separated list of numbers that index the cell\n" +
+            "    on the pattern in a 1-based manner in left to right and top to bottom order,\n" +
+            "    i.e. the top-left cell is indexed with 1, whereas the bottom-right cell\n" +
+            "    is indexed with 9. Example: 1234\n" +
+            "\n" +
+            "locksettings set-pin: sets a PIN\n" +
+            "\n" +
+            "locksettings set-password: sets a password\n" +
+            "\n" +
+            "locksettings clear: clears the unlock credential\n";
+
+    public static void main(String[] args) {
+        (new LockSettingsCmd()).run(args);
+    }
+
+    @Override
+    public void onShowUsage(PrintStream out) {
+        out.println(USAGE);
+    }
+
+    @Override
+    public void onRun() throws Exception {
+        ILockSettings lockSettings = ILockSettings.Stub.asInterface(
+                ServiceManager.getService("lock_settings"));
+        lockSettings.asBinder().shellCommand(FileDescriptor.in, FileDescriptor.out,
+                FileDescriptor.err, getRawArgs(), new ShellCallback(), new ResultReceiver(null) {});
+    }
+}
diff --git a/compiled-classes-phone b/compiled-classes-phone
index 8428e41..33e3e04 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -3610,9 +3610,9 @@
 android.service.notification.NotificationListenerService$Ranking
 android.service.notification.NotificationListenerService$RankingMap
 android.service.notification.NotificationListenerService$RankingMap$1
-android.service.notification.NotificationRankerService
-android.service.notification.NotificationRankerService$MyHandler
-android.service.notification.NotificationRankerService$NotificationRankingServiceWrapper
+android.service.notification.NotificationAssistantService
+android.service.notification.NotificationAssistantService$MyHandler
+android.service.notification.NotificationAssistantService$NotificationRankingServiceWrapper
 android.service.notification.NotificationRankingUpdate
 android.service.notification.NotificationRankingUpdate$1
 android.service.notification.StatusBarNotification
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 0552d34..58f5a78 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -1494,22 +1494,22 @@
         public void onFocusChange(View v, boolean hasFocus) {
             if (!hasFocus) {
                 v.setOnFocusChangeListener(null);
-                final View focused = mFocusRoot.findFocus();
-                if (focused != null) {
-                    focused.setOnFocusChangeListener(this);
-                } else {
-                    mFocusRoot.post(this);
-                }
+                mFocusRoot.post(this);
             }
         }
 
         @Override
         public void run() {
-            if (mContainer != null) {
-                mContainer.setTouchscreenBlocksFocus(true);
-            }
-            if (mToolbar != null) {
-                mToolbar.setTouchscreenBlocksFocus(true);
+            final View focused = mFocusRoot.findFocus();
+            if (focused != null) {
+                focused.setOnFocusChangeListener(this);
+            } else {
+                if (mContainer != null) {
+                    mContainer.setTouchscreenBlocksFocus(true);
+                }
+                if (mToolbar != null) {
+                    mToolbar.setTouchscreenBlocksFocus(true);
+                }
             }
         }
     }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index df970a4..4a39e4a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -102,7 +102,7 @@
         }
 
         @Override
-        public void onUidGone(int uid) {
+        public void onUidGone(int uid, boolean disabled) {
             mListener.onUidImportance(uid, RunningAppProcessInfo.IMPORTANCE_GONE);
         }
 
@@ -111,7 +111,7 @@
         }
 
         @Override
-        public void onUidIdle(int uid) {
+        public void onUidIdle(int uid, boolean disabled) {
         }
     }
 
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index e56fe0f..38e3572 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -194,4 +194,9 @@
      * @return {@code true} if system is ready, {@code false} otherwise.
      */
     public abstract boolean isSystemReady();
+
+    /**
+     * Called when the trusted state of Keyguard has changed.
+     */
+    public abstract void notifyKeyguardTrustedChanged();
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3e8d90b..a3414f4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -80,6 +80,11 @@
 import android.os.Trace;
 import android.os.TransactionTooLargeException;
 import android.os.UserHandle;
+import android.provider.BlockedNumberContract;
+import android.provider.CalendarContract;
+import android.provider.CallLog;
+import android.provider.ContactsContract;
+import android.provider.Downloads;
 import android.provider.Settings;
 import android.security.NetworkSecurityPolicy;
 import android.security.net.config.NetworkSecurityConfigProvider;
@@ -5823,6 +5828,22 @@
         final String auths[] = holder.info.authority.split(";");
         final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
 
+        if (provider != null) {
+            // If this provider is hosted by the core OS and cannot be upgraded,
+            // then I guess we're okay doing blocking calls to it.
+            for (String auth : auths) {
+                switch (auth) {
+                    case ContactsContract.AUTHORITY:
+                    case CallLog.AUTHORITY:
+                    case CallLog.SHADOW_AUTHORITY:
+                    case BlockedNumberContract.AUTHORITY:
+                    case CalendarContract.AUTHORITY:
+                    case Downloads.Impl.AUTHORITY:
+                        Binder.allowBlocking(provider.asBinder());
+                }
+            }
+        }
+
         final ProviderClientRecord pcr = new ProviderClientRecord(
                 auths, provider, localProvider, holder);
         for (String auth : auths) {
@@ -5971,7 +5992,6 @@
                 retHolder = prc.holder;
             }
         }
-
         return retHolder;
     }
 
diff --git a/core/java/android/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java
index ba79108..d8d7340 100644
--- a/core/java/android/app/EphemeralResolverService.java
+++ b/core/java/android/app/EphemeralResolverService.java
@@ -40,6 +40,7 @@
     public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
     public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
     private static final String EXTRA_PREFIX = "android.app.PREFIX";
+    private static final String EXTRA_HOSTNAME = "android.app.HOSTNAME";
     private Handler mHandler;
 
     /**
@@ -49,9 +50,29 @@
      * @param prefixMask A mask that was applied to each digest prefix. This should
      *      be used when comparing against the digest prefixes as all bits might
      *      not be set.
+     * @deprecated use {@link #onGetEphemeralResolveInfo(int[])} instead
      */
+    @Deprecated
     public abstract List<EphemeralResolveInfo> onEphemeralResolveInfoList(
-            int digestPrefix[], int prefixMask);
+            int digestPrefix[], int prefix);
+
+    /**
+     * Called to retrieve resolve info for ephemeral applications.
+     *
+     * @param digestPrefix The hash prefix of the ephemeral's domain.
+     */
+    public List<EphemeralResolveInfo> onGetEphemeralResolveInfo(int digestPrefix[]) {
+        return onEphemeralResolveInfoList(digestPrefix, 0xFFFFF000);
+    }
+
+    /**
+     * Called to retrieve intent filters for ephemeral applications.
+     *
+     * @param digestPrefix The hash prefix of the ephemeral's domain.
+     */
+    public List<EphemeralResolveInfo> onGetEphemeralIntentFilter(int digestPrefix[]) {
+        throw new IllegalStateException("Must define");
+    }
 
     @Override
     public final void attachBaseContext(Context base) {
@@ -64,9 +85,20 @@
         return new IEphemeralResolver.Stub() {
             @Override
             public void getEphemeralResolveInfoList(
-                    IRemoteCallback callback, int digestPrefix[], int prefixMask, int sequence) {
+                    IRemoteCallback callback, int digestPrefix[], int sequence) {
                 final Message msg = mHandler.obtainMessage(
-                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, prefixMask, sequence, callback);
+                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, sequence, 0, callback);
+                final Bundle data = new Bundle();
+                data.putIntArray(EXTRA_PREFIX, digestPrefix);
+                msg.setData(data);
+                msg.sendToTarget();
+            }
+
+            @Override
+            public void getEphemeralIntentFilterList(
+                    IRemoteCallback callback, int digestPrefix[], int sequence) {
+                final Message msg = mHandler.obtainMessage(
+                        ServiceHandler.MSG_GET_EPHEMERAL_INTENT_FILTER, sequence, 0, callback);
                 final Bundle data = new Bundle();
                 data.putIntArray(EXTRA_PREFIX, digestPrefix);
                 msg.setData(data);
@@ -77,6 +109,7 @@
 
     private final class ServiceHandler extends Handler {
         public static final int MSG_GET_EPHEMERAL_RESOLVE_INFO = 1;
+        public static final int MSG_GET_EPHEMERAL_INTENT_FILTER = 2;
 
         public ServiceHandler(Looper looper) {
             super(looper, null /*callback*/, true /*async*/);
@@ -91,9 +124,23 @@
                     final IRemoteCallback callback = (IRemoteCallback) message.obj;
                     final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
                     final List<EphemeralResolveInfo> resolveInfo =
-                            onEphemeralResolveInfoList(digestPrefix, message.arg1);
+                            onGetEphemeralResolveInfo(digestPrefix);
                     final Bundle data = new Bundle();
-                    data.putInt(EXTRA_SEQUENCE, message.arg2);
+                    data.putInt(EXTRA_SEQUENCE, message.arg1);
+                    data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
+                    try {
+                        callback.sendResult(data);
+                    } catch (RemoteException e) {
+                    }
+                } break;
+
+                case MSG_GET_EPHEMERAL_INTENT_FILTER: {
+                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
+                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
+                    final List<EphemeralResolveInfo> resolveInfo =
+                            onGetEphemeralIntentFilter(digestPrefix);
+                    final Bundle data = new Bundle();
+                    data.putInt(EXTRA_SEQUENCE, message.arg1);
                     data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
                     try {
                         callback.sendResult(data);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 6a3a799..9fe34c0 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -499,7 +499,7 @@
     boolean supportsLocalVoiceInteraction() = 365;
     void notifyPinnedStackAnimationEnded() = 366;
     void removeStack(int stackId) = 367;
-    void setLenientBackgroundCheck(boolean enabled) = 368;
+    void makePackageIdle(String packageName, int userId) = 368;
     int getMemoryTrimLevel() = 369;
     /**
      * Resizes the pinned stack.
diff --git a/core/java/android/app/IEphemeralResolver.aidl b/core/java/android/app/IEphemeralResolver.aidl
index ee869ea..e0cef83 100644
--- a/core/java/android/app/IEphemeralResolver.aidl
+++ b/core/java/android/app/IEphemeralResolver.aidl
@@ -21,5 +21,8 @@
 /** @hide */
 oneway interface IEphemeralResolver {
     void getEphemeralResolveInfoList(IRemoteCallback callback, in int[] digestPrefix,
-            int prefixMask, int sequence);
+            int sequence);
+
+    void getEphemeralIntentFilterList(IRemoteCallback callback, in int[] digestPrefix,
+            int sequence);
 }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index ee81c58..15b99c6 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -94,8 +94,8 @@
     void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
     void setInterruptionFilter(String pkg, int interruptionFilter);
 
-    void applyAdjustmentFromRankerService(in INotificationListener token, in Adjustment adjustment);
-    void applyAdjustmentsFromRankerService(in INotificationListener token, in List<Adjustment> adjustments);
+    void applyAdjustmentFromAssistantService(in INotificationListener token, in Adjustment adjustment);
+    void applyAdjustmentsFromAssistantService(in INotificationListener token, in List<Adjustment> adjustments);
 
     ComponentName getEffectsSuppressor();
     boolean matchesCallFilter(in Bundle extras);
diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl
index fa8d0c9..64cb9b1 100644
--- a/core/java/android/app/IUidObserver.aidl
+++ b/core/java/android/app/IUidObserver.aidl
@@ -26,7 +26,7 @@
     /**
      * Report that there are no longer any processes running for a uid.
      */
-    void onUidGone(int uid);
+    void onUidGone(int uid, boolean disabled);
 
     /**
      * Report that a uid is now active (no longer idle).
@@ -37,5 +37,5 @@
      * Report that a uid is idle -- it has either been running in the background for
      * a sufficient period of time, or all of its processes have gone away.
      */
-    void onUidIdle(int uid);
+    void onUidIdle(int uid, boolean disabled);
 }
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 353c640..3de159a 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.media.AudioManager;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -572,7 +573,7 @@
             if (DBG) Log.d(TAG, "Proxy object connected");
             try {
                 mServiceLock.writeLock().lock();
-                mService = IBluetoothA2dp.Stub.asInterface(service);
+                mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
             } finally {
                 mServiceLock.writeLock().unlock();
             }
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 74302f2..9dfc4b4 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -20,6 +20,7 @@
 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;
@@ -481,7 +482,7 @@
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothA2dpSink.Stub.asInterface(service);
+            mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
 
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index a395aa4..0261b1b 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -22,6 +22,7 @@
 import android.content.ServiceConnection;
 import android.media.MediaMetadata;
 import android.media.session.PlaybackState;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
@@ -284,7 +285,7 @@
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothAvrcpController.Stub.asInterface(service);
+            mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
 
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index f46a3b3..28421eb 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -20,6 +20,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
 import android.content.Context;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -1037,7 +1038,7 @@
         @Override
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothHeadset.Stub.asInterface(service);
+            mService = IBluetoothHeadset.Stub.asInterface(Binder.allowBlocking(service));
             mHandler.sendMessage(mHandler.obtainMessage(
                     MESSAGE_HEADSET_SERVICE_CONNECTED));
         }
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 93790fe..c7c64c4 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -1122,7 +1123,7 @@
         @Override
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothHeadsetClient.Stub.asInterface(service);
+            mService = IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
 
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index 4949c24..8d77888 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -522,7 +523,7 @@
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothHealth.Stub.asInterface(service);
+            mService = IBluetoothHealth.Stub.asInterface(Binder.allowBlocking(service));
 
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, BluetoothHealth.this);
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 252e3d2..e3288f3 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -22,6 +22,7 @@
 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;
@@ -479,7 +480,7 @@
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
-            mService = IBluetoothInputDevice.Stub.asInterface(service);
+            mService = IBluetoothInputDevice.Stub.asInterface(Binder.allowBlocking(service));
 
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 7f57acf..2e73051 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -371,7 +371,7 @@
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) log("Proxy object connected");
-            mService = IBluetoothMap.Stub.asInterface(service);
+            mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this);
             }
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 744f942..2a026a9 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -22,6 +22,7 @@
 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;
@@ -368,7 +369,7 @@
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
-            mPanService = IBluetoothPan.Stub.asInterface(service);
+            mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
 
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.PAN,
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index eab4c6f..9f00e1a 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.RemoteException;
+import android.os.Binder;
 import android.os.IBinder;
 import android.util.Log;
 
@@ -288,7 +289,7 @@
             if (DBG) {
                 log("Proxy object connected");
             }
-            mService = IBluetoothPbapClient.Stub.asInterface(service);
+            mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, BluetoothPbapClient.this);
             }
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index e70c936..89c1bf8 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.RemoteException;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.ServiceManager;
 import android.util.Log;
@@ -393,7 +394,7 @@
     private ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) log("Proxy object connected");
-            mService = IBluetoothSap.Stub.asInterface(service);
+            mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this);
             }
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index 6ad442b..dde0ac6 100755
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -54,7 +54,7 @@
     boolean getAudioRouteAllowed();
     boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device);
     boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device);
-    void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
+    oneway void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
     void clccResponse(int index, int direction, int status, int mode, boolean mpty,
                       String number, int type);
     boolean enableWBS();
diff --git a/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl b/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl
index 96c59e2..541583f 100755
--- a/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl
+++ b/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl
@@ -24,7 +24,7 @@
  *
  * {@hide}
  */
-interface IBluetoothProfileServiceConnection {
+oneway interface IBluetoothProfileServiceConnection {
     void onServiceConnected(in ComponentName comp, in IBinder service);
     void onServiceDisconnected(in ComponentName comp);
 }
diff --git a/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl b/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
index feccdce..0da4e88 100644
--- a/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
@@ -21,7 +21,7 @@
  *
  * {@hide}
  */
-interface IBluetoothStateChangeCallback
+oneway interface IBluetoothStateChangeCallback
 {
     void onBluetoothStateChange(boolean on);
 }
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index f53ca94..9e87230 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -30,10 +30,24 @@
  * @hide
  */
 public class OobData implements Parcelable {
+    private byte[] leBluetoothDeviceAddress;
     private byte[] securityManagerTk;
     private byte[] leSecureConnectionsConfirmation;
     private byte[] leSecureConnectionsRandom;
 
+    public byte[] getLeBluetoothDeviceAddress() {
+        return leBluetoothDeviceAddress;
+    }
+
+    /**
+     * Sets the LE Bluetooth Device Address value to be used during LE pairing.
+     * The value shall be 7 bytes. Please see Bluetooth CSSv6, Part A 1.16 for
+     * a detailed description.
+     */
+    public void setLeBluetoothDeviceAddress(byte[] leBluetoothDeviceAddress) {
+        this.leBluetoothDeviceAddress = leBluetoothDeviceAddress;
+    }
+
     public byte[] getSecurityManagerTk() {
         return securityManagerTk;
     }
@@ -66,6 +80,7 @@
     public OobData() { }
 
     private OobData(Parcel in) {
+        leBluetoothDeviceAddress = in.createByteArray();
         securityManagerTk = in.createByteArray();
         leSecureConnectionsConfirmation = in.createByteArray();
         leSecureConnectionsRandom = in.createByteArray();
@@ -77,6 +92,7 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
+        out.writeByteArray(leBluetoothDeviceAddress);
         out.writeByteArray(securityManagerTk);
         out.writeByteArray(leSecureConnectionsConfirmation);
         out.writeByteArray(leSecureConnectionsRandom);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 4769bd0..439e1ff 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -422,6 +422,7 @@
 
             if (reply.readInt() != 0) {
                 BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
+                Binder.copyAllowBlocking(mRemote, (d.cursor != null) ? d.cursor.asBinder() : null);
                 adaptor.initialize(d);
             } else {
                 adaptor.close();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 322cc7b..3964e0a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3338,6 +3338,14 @@
     public static final String VOICE_INTERACTION_MANAGER_SERVICE = "voiceinteraction";
 
     /**
+     * Official published name of the (internal) auto-fill service.
+     *
+     * @hide
+     * @see #getSystemService
+     */
+    public static final String AUTO_FILL_MANAGER_SERVICE = "autofill";
+
+    /**
      * Use with {@link #getSystemService} to access the
      * {@link com.android.server.voiceinteraction.SoundTriggerService}.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9015c4b..a9e987a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1713,6 +1713,16 @@
     public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
 
     /**
+     * Intent extra: An app split name.
+     * <p>
+     * Type: String
+     * </p>
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
+
+    /**
      * Intent extra: An extra for specifying whether a result is needed.
      * <p>
      * Type: boolean
diff --git a/core/java/android/content/pm/EphemeralIntentFilter.java b/core/java/android/content/pm/EphemeralIntentFilter.java
new file mode 100644
index 0000000..0674e7c
--- /dev/null
+++ b/core/java/android/content/pm/EphemeralIntentFilter.java
@@ -0,0 +1,96 @@
+/*
+ * 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.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.IntentFilter;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Information about an ephemeral application intent filter.
+ * @hide
+ */
+@SystemApi
+public final class EphemeralIntentFilter implements Parcelable {
+    private final String mSplitName;
+    /** The filters used to match domain */
+    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
+
+    public EphemeralIntentFilter(@Nullable String splitName, @NonNull List<IntentFilter> filters) {
+        if (filters == null || filters.size() == 0) {
+            throw new IllegalArgumentException();
+        }
+        mSplitName = splitName;
+        mFilters.addAll(filters);
+    }
+
+    EphemeralIntentFilter(Parcel in) {
+        mSplitName = in.readString();
+        in.readList(mFilters, null /*loader*/);
+    }
+
+    public String getSplitName() {
+        return mSplitName;
+    }
+
+    public List<IntentFilter> getFilters() {
+        return mFilters;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mSplitName);
+        out.writeList(mFilters);
+    }
+
+    public static final Parcelable.Creator<EphemeralIntentFilter> CREATOR
+            = new Parcelable.Creator<EphemeralIntentFilter>() {
+        public EphemeralIntentFilter createFromParcel(Parcel in) {
+            return new EphemeralIntentFilter(in);
+        }
+
+        public EphemeralIntentFilter[] newArray(int size) {
+            return new EphemeralIntentFilter[size];
+        }
+    };
+
+    /** @hide */
+    public static final class EphemeralResolveIntentInfo extends IntentFilter {
+        private final EphemeralIntentFilter mResolveInfo;
+
+        public EphemeralResolveIntentInfo(@NonNull IntentFilter orig,
+                @NonNull EphemeralIntentFilter resolveInfo) {
+            super(orig);
+            this.mResolveInfo = resolveInfo;
+        }
+
+        public EphemeralIntentFilter getEphemeralResolveInfo() {
+            return mResolveInfo;
+        }
+    }
+}
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
index fc3b958..3bed06b 100644
--- a/core/java/android/content/pm/EphemeralResolveInfo.java
+++ b/core/java/android/content/pm/EphemeralResolveInfo.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.IntentFilter;
 import android.net.Uri;
@@ -41,27 +42,54 @@
     private final EphemeralDigest mDigest;
     private final String mPackageName;
     /** The filters used to match domain */
-    private final List<IntentFilter> mFilters = new ArrayList<IntentFilter>();
+    private final List<EphemeralIntentFilter> mFilters;
+    /** Filters only for legacy clients */
+    @Deprecated
+    private List<IntentFilter> mLegacyFilters;
 
+    @Deprecated
     public EphemeralResolveInfo(@NonNull Uri uri, @NonNull String packageName,
             @NonNull List<IntentFilter> filters) {
-        // validate arguments
-        if (uri == null
-                || packageName == null
-                || filters == null
-                || filters.size() == 0) {
+        if (uri == null || packageName == null || filters == null || filters.isEmpty()) {
             throw new IllegalArgumentException();
         }
-
-        mDigest = new EphemeralDigest(uri, 0xFFFFFFFF, -1);
-        mFilters.addAll(filters);
+        mDigest = new EphemeralDigest(uri.getHost());
         mPackageName = packageName;
+        mFilters = new ArrayList<EphemeralIntentFilter>();
+        mFilters.add(new EphemeralIntentFilter(packageName, filters));
+        mLegacyFilters = new ArrayList<IntentFilter>(filters.size());
+        mLegacyFilters.addAll(filters);
+    }
+
+    public EphemeralResolveInfo(@NonNull EphemeralDigest digest, @Nullable String packageName,
+            @Nullable List<EphemeralIntentFilter> filters) {
+        // validate arguments
+        if ((packageName == null && (filters != null && filters.size() != 0))
+                || (packageName != null && (filters == null || filters.size() == 0))) {
+            throw new IllegalArgumentException();
+        }
+        mDigest = digest;
+        if (filters != null) {
+            mFilters = new ArrayList<EphemeralIntentFilter>(filters.size());
+            mFilters.addAll(filters);
+        } else {
+            mFilters = null;
+        }
+        mPackageName = packageName;
+    }
+
+    public EphemeralResolveInfo(@NonNull String hostName, @Nullable String packageName,
+            @Nullable List<EphemeralIntentFilter> filters) {
+        this(new EphemeralDigest(hostName), packageName, filters);
     }
 
     EphemeralResolveInfo(Parcel in) {
         mDigest = in.readParcelable(null /*loader*/);
         mPackageName = in.readString();
+        mFilters = new ArrayList<EphemeralIntentFilter>();
         in.readList(mFilters, null /*loader*/);
+        mLegacyFilters = new ArrayList<IntentFilter>();
+        in.readList(mLegacyFilters, null /*loader*/);
     }
 
     public byte[] getDigestBytes() {
@@ -76,7 +104,12 @@
         return mPackageName;
     }
 
+    @Deprecated
     public List<IntentFilter> getFilters() {
+        return mLegacyFilters;
+    }
+
+    public List<EphemeralIntentFilter> getIntentFilters() {
         return mFilters;
     }
 
@@ -90,6 +123,7 @@
         out.writeParcelable(mDigest, flags);
         out.writeString(mPackageName);
         out.writeList(mFilters);
+        out.writeList(mLegacyFilters);
     }
 
     public static final Parcelable.Creator<EphemeralResolveInfo> CREATOR
@@ -106,16 +140,23 @@
     /** @hide */
     public static final class EphemeralResolveIntentInfo extends IntentFilter {
         private final EphemeralResolveInfo mResolveInfo;
+        private final String mSplitName;
 
         public EphemeralResolveIntentInfo(@NonNull IntentFilter orig,
-                @NonNull EphemeralResolveInfo resolveInfo) {
+                @NonNull EphemeralResolveInfo resolveInfo,
+                @Nullable String splitName) {
             super(orig);
-            this.mResolveInfo = resolveInfo;
+            mResolveInfo = resolveInfo;
+            mSplitName = splitName;
         }
 
         public EphemeralResolveInfo getEphemeralResolveInfo() {
             return mResolveInfo;
         }
+
+        public String getSplitName() {
+            return mSplitName;
+        }
     }
 
     /**
@@ -129,17 +170,25 @@
      *
      * @hide
      */
+    @SystemApi
     public static final class EphemeralDigest implements Parcelable {
+        private static final int DIGEST_MASK = 0xfffff000;
+        private static final int DIGEST_PREFIX_COUNT = 5;
         /** Full digest of the domain hashes */
         private final byte[][] mDigestBytes;
         /** The first 4 bytes of the domain hashes */
         private final int[] mDigestPrefix;
 
-        public EphemeralDigest(@NonNull Uri uri, int digestMask, int maxDigests) {
-            if (uri == null) {
+        public EphemeralDigest(@NonNull String hostName) {
+            this(hostName, -1 /*maxDigests*/);
+        }
+
+        /** @hide */
+        public EphemeralDigest(@NonNull String hostName, int maxDigests) {
+            if (hostName == null) {
                 throw new IllegalArgumentException();
             }
-            mDigestBytes = generateDigest(uri, maxDigests);
+            mDigestBytes = generateDigest(hostName.toLowerCase(Locale.ENGLISH), maxDigests);
             mDigestPrefix = new int[mDigestBytes.length];
             for (int i = 0; i < mDigestBytes.length; i++) {
                 mDigestPrefix[i] =
@@ -147,31 +196,32 @@
                                 | (mDigestBytes[i][1] & 0xFF) << 16
                                 | (mDigestBytes[i][2] & 0xFF) << 8
                                 | (mDigestBytes[i][3] & 0xFF) << 0)
-                        & digestMask;
+                        & DIGEST_MASK;
             }
         }
 
-        private static byte[][] generateDigest(Uri uri, int maxDigests) {
+        private static byte[][] generateDigest(String hostName, int maxDigests) {
             ArrayList<byte[]> digests = new ArrayList<>();
             try {
-                final String host = uri.getHost().toLowerCase(Locale.ENGLISH);
                 final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
                 if (maxDigests <= 0) {
-                    final byte[] hostBytes = host.getBytes();
+                    final byte[] hostBytes = hostName.getBytes();
                     digests.add(digest.digest(hostBytes));
                 } else {
-                    int prevDot = host.lastIndexOf('.');
-                    prevDot = host.lastIndexOf('.', prevDot - 1);
+                    int prevDot = hostName.lastIndexOf('.');
+                    prevDot = hostName.lastIndexOf('.', prevDot - 1);
                     // shortcut for short URLs
                     if (prevDot < 0) {
-                        digests.add(digest.digest(host.getBytes()));
+                        digests.add(digest.digest(hostName.getBytes()));
                     } else {
-                        byte[] hostBytes = host.substring(prevDot + 1, host.length()).getBytes();
+                        byte[] hostBytes =
+                                hostName.substring(prevDot + 1, hostName.length()).getBytes();
                         digests.add(digest.digest(hostBytes));
                         int digestCount = 1;
                         while (prevDot >= 0 && digestCount < maxDigests) {
-                            prevDot = host.lastIndexOf('.', prevDot - 1);
-                            hostBytes = host.substring(prevDot + 1, host.length()).getBytes();
+                            prevDot = hostName.lastIndexOf('.', prevDot - 1);
+                            hostBytes =
+                                    hostName.substring(prevDot + 1, hostName.length()).getBytes();
                             digests.add(digest.digest(hostBytes));
                             digestCount++;
                         }
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 1f013ae..2aa7ac6 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -162,6 +162,12 @@
     public abstract boolean isPackageDataProtected(int userId, String packageName);
 
     /**
+     * Returns {@code true} if a given package is installed as ephemeral. Otherwise, returns
+     * {@code false}.
+     */
+    public abstract boolean isPackageEphemeral(int userId, String packageName);
+
+    /**
      * Gets whether the package was ever launched.
      * @param packageName The package name.
      * @param userId The user for which to check.
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index b5df4d7..86dbe8a 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.IntentFilter;
+import android.content.pm.EphemeralResolveInfo.EphemeralResolveIntentInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -65,7 +66,7 @@
      * only be set in specific circumstances.
      * @hide
      */
-    public EphemeralResolveInfo ephemeralResolveInfo;
+    public EphemeralResolveIntentInfo ephemeralIntentInfo;
 
     /**
      * The IntentFilter that was matched for this ResolveInfo.
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
index d2c3d75..3fe645c 100644
--- a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
@@ -25,7 +25,7 @@
  *
  * @hide
  */
-interface IActivityRecognitionHardwareClient {
+oneway interface IActivityRecognitionHardwareClient {
     /**
      * Hardware Activity-Recognition availability event.
      *
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index a5b4eb5..e0a026e 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -38,9 +38,15 @@
     public static final int PROVISIONING_OK    = 1;
     public static final int PROVISIONING_FAIL  = 2;
     public static final int COMPLETE_LIFECYCLE = 3;
+    /** @hide */ public static final int ERROR_STARTING_IPV4 = 4;
+    /** @hide */ public static final int ERROR_STARTING_IPV6 = 5;
+    /** @hide */ public static final int ERROR_STARTING_IPREACHABILITYMONITOR = 6;
 
     /** {@hide} */
-    @IntDef(value = {PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE})
+    @IntDef(value = {
+            PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
+            ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
+    })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
 
@@ -95,6 +101,7 @@
 
     final static class Decoder {
         static final SparseArray<String> constants = MessageUtils.findMessageNames(
-                new Class[]{IpManagerEvent.class}, new String[]{"PROVISIONING_", "COMPLETE_"});
+                new Class[]{IpManagerEvent.class},
+                new String[]{"PROVISIONING_", "COMPLETE_", "ERROR_"});
     }
 }
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 7b7533b..0136979 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -75,36 +75,35 @@
     /**
      * Control whether dump() calls are allowed.
      */
-    private static String sDumpDisabled = null;
+    private static volatile String sDumpDisabled = null;
 
     /**
      * Global transaction tracker instance for this process.
      */
-    private static TransactionTracker sTransactionTracker = null;
+    private static volatile TransactionTracker sTransactionTracker = null;
 
     // Transaction tracking code.
 
     /**
      * Flag indicating whether we should be tracing transact calls.
-     *
      */
-    private static boolean sTracingEnabled = false;
+    private static volatile boolean sTracingEnabled = false;
 
     /**
      * Enable Binder IPC tracing.
      *
      * @hide
      */
-    public static void  enableTracing() {
+    public static void enableTracing() {
         sTracingEnabled = true;
-    };
+    }
 
     /**
      * Disable Binder IPC tracing.
      *
      * @hide
      */
-    public static void  disableTracing() {
+    public static void disableTracing() {
         sTracingEnabled = false;
     }
 
@@ -128,6 +127,59 @@
         return sTransactionTracker;
     }
 
+    /** {@hide} */
+    static volatile boolean sWarnOnBlocking = false;
+
+    /**
+     * Warn if any blocking binder transactions are made out from this process.
+     * This is typically only useful for the system process, to prevent it from
+     * blocking on calls to external untrusted code. Instead, all outgoing calls
+     * that require a result must be sent as {@link IBinder#FLAG_ONEWAY} calls
+     * which deliver results through a callback interface.
+     *
+     * @hide
+     */
+    public static void setWarnOnBlocking(boolean warnOnBlocking) {
+        sWarnOnBlocking = warnOnBlocking;
+    }
+
+    /**
+     * Allow blocking calls on the given interface, overriding the requested
+     * value of {@link #setWarnOnBlocking(boolean)}.
+     * <p>
+     * This should only be rarely called when you are <em>absolutely sure</em>
+     * the remote interface is a built-in system component that can never be
+     * upgraded. In particular, this <em>must never</em> be called for
+     * interfaces hosted by package that could be upgraded or replaced,
+     * otherwise you risk system instability if that remote interface wedges.
+     *
+     * @hide
+     */
+    public static IBinder allowBlocking(IBinder binder) {
+        try {
+            if (binder instanceof BinderProxy) {
+                ((BinderProxy) binder).mWarnOnBlocking = false;
+            } else if (binder != null
+                    && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
+                Log.w(TAG, "Unable to allow blocking on interface " + binder);
+            }
+        } catch (RemoteException ignored) {
+        }
+        return binder;
+    }
+
+    /**
+     * Inherit the current {@link #allowBlocking(IBinder)} value from one given
+     * interface to another.
+     *
+     * @hide
+     */
+    public static void copyAllowBlocking(IBinder fromBinder, IBinder toBinder) {
+        if (fromBinder instanceof BinderProxy && toBinder instanceof BinderProxy) {
+            ((BinderProxy) toBinder).mWarnOnBlocking = ((BinderProxy) fromBinder).mWarnOnBlocking;
+        }
+    }
+
     /* mObject is used by native code, do not remove or rename */
     private long mObject;
     private IInterface mOwner;
@@ -322,9 +374,7 @@
      * re-enabled.
      */
     public static void setDumpDisabled(String msg) {
-        synchronized (Binder.class) {
-            sDumpDisabled = msg;
-        }
+        sDumpDisabled = msg;
     }
 
     /**
@@ -400,10 +450,7 @@
     }
 
     void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        final String disabled;
-        synchronized (Binder.class) {
-            disabled = sDumpDisabled;
-        }
+        final String disabled = sDumpDisabled;
         if (disabled == null) {
             try {
                 dump(fd, pw, args);
@@ -612,6 +659,9 @@
 }
 
 final class BinderProxy implements IBinder {
+    // Assume the process-wide default value when created
+    volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
+
     public native boolean pingBinder();
     public native boolean isBinderAlive();
 
@@ -621,6 +671,15 @@
 
     public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
         Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
+
+        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
+            // For now, avoid spamming the log by disabling after we've logged
+            // about this interface at least once
+            mWarnOnBlocking = false;
+            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
+                    new Throwable());
+        }
+
         final boolean tracingEnabled = Binder.isTracingEnabled();
         if (tracingEnabled) {
             final Throwable tr = new Throwable();
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 640105c..e11494d 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -36,7 +36,8 @@
         }
 
         // Find the service manager
-        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
+        sServiceManager = ServiceManagerNative
+                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
         return sServiceManager;
     }
 
@@ -52,7 +53,7 @@
             if (service != null) {
                 return service;
             } else {
-                return getIServiceManager().getService(name);
+                return Binder.allowBlocking(getIServiceManager().getService(name));
             }
         } catch (RemoteException e) {
             Log.e(TAG, "error in getService", e);
@@ -117,7 +118,7 @@
             if (service != null) {
                 return service;
             } else {
-                return getIServiceManager().checkService(name);
+                return Binder.allowBlocking(getIServiceManager().checkService(name));
             }
         } catch (RemoteException e) {
             Log.e(TAG, "error in checkService", e);
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index b826584..a280e59 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -41,6 +41,8 @@
     public static final class Impl implements BaseColumns {
         private Impl() {}
 
+        public static final String AUTHORITY = "downloads";
+
         /**
          * The permission to access the download manager
          */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1b905a0..79b42ba 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4715,6 +4715,13 @@
         public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
 
         /**
+         * The currently selected auto-fill service flattened ComponentName.
+         * @hide
+         */
+        @TestApi
+        public static final String AUTO_FILL_SERVICE = "auto_fill_service";
+
+        /**
          * bluetooth HCI snoop log configuration
          * @hide
          */
@@ -6114,6 +6121,15 @@
         public static final String ASSIST_DISCLOSURE_ENABLED = "assist_disclosure_enabled";
 
         /**
+         * Name of the service components that the current user has explicitly allowed to
+         * see and assist with all of the user's notifications.
+         *
+         * @hide
+         */
+        public static final String ENABLED_NOTIFICATION_ASSISTANT =
+                "enabled_notification_assistant";
+
+        /**
          * Names of the service components that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
          *
@@ -8613,13 +8629,6 @@
         public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
 
         /**
-         * @hide
-         * If not 0, the activity manager will implement a looser version of background
-         * check that is more compatible with existing apps.
-         */
-        public static final String LENIENT_BACKGROUND_CHECK = "lenient_background_check";
-
-        /**
          * Use Dock audio output for media:
          *      0 = disabled
          *      1 = enabled
@@ -8956,24 +8965,6 @@
         public static final String ENABLE_EPHEMERAL_FEATURE = "enable_ephemeral_feature";
 
         /**
-         * A mask applied to the ephemeral hash to generate the hash prefix.
-         * <p>
-         * Type: int
-         *
-         * @hide
-         */
-        public static final String EPHEMERAL_HASH_PREFIX_MASK = "ephemeral_hash_prefix_mask";
-
-        /**
-         * Number of hash prefixes to send during ephemeral resolution.
-         * <p>
-         * Type: int
-         *
-         * @hide
-         */
-        public static final String EPHEMERAL_HASH_PREFIX_COUNT = "ephemeral_hash_prefix_count";
-
-        /**
          * The duration for caching uninstalled ephemeral apps.
          * <p>
          * Type: long
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
new file mode 100644
index 0000000..14ce009b
--- /dev/null
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.app.assist.AssistStructure;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+/**
+ * Top-level service of the current auto-fill service for a given user.
+ */
+// TODO: expand documentation
+public abstract class AutoFillService extends Service {
+
+    private static final String TAG = "AutoFillService";
+    private static final boolean DEBUG = true; // TODO: set to false once stable
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     * To be supported, the service must also require the
+     * {@link android.Manifest.permission#BIND_AUTO_FILL} permission so
+     * that other applications can not abuse it.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
+
+    private static final int MSG_READY = 1;
+    private static final int MSG_NEW_SESSION = 2;
+    private static final int MSG_SESSION_FINISHED = 3;
+    private static final int MSG_SHUTDOWN = 4;
+
+    // TODO: add metadata?
+
+    private final IAutoFillService mInterface = new IAutoFillService.Stub() {
+        @Override
+        public void ready() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_READY));
+        }
+
+        @Override
+        public void newSession(String token, Bundle data, int flags,
+                AssistStructure structure) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOOO(MSG_NEW_SESSION,
+                    flags, token, data, structure));
+        }
+
+        @Override
+        public void finishSession(String token) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_SESSION_FINISHED, token));
+        }
+
+        @Override
+        public void shutdown() {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_SHUTDOWN));
+        }
+    };
+
+    private final HandlerCaller.Callback mHandlerCallback = new HandlerCaller.Callback() {
+
+        @Override
+        public void executeMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_READY: {
+                    onReady();
+                    break;
+                } case MSG_NEW_SESSION: {
+                    final SomeArgs args = (SomeArgs) msg.obj;
+                    final int flags = args.argi1;
+                    final String token = (String) args.arg1;
+                    final Bundle data = (Bundle) args.arg2;
+                    final AssistStructure assistStructure = (AssistStructure) args.arg3;
+                    onNewSession(token, data, flags, assistStructure);
+                    break;
+                } case MSG_SESSION_FINISHED: {
+                    final String token = (String) msg.obj;
+                    onSessionFinished(token);
+                    break;
+                } case MSG_SHUTDOWN: {
+                    onShutdown();
+                    break;
+                } default: {
+                    Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
+                }
+            }
+        }
+    };
+
+    private HandlerCaller mHandlerCaller;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(), mHandlerCallback, true);
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        return null;
+    }
+
+    /**
+     * Called during service initialization to tell you when the system is ready
+     * to receive interaction from it.
+     *
+     * <p>You should generally do initialization here rather than in {@link #onCreate}.
+     *
+     * <p>Sub-classes should call it first, since it sets the reference to the sytem-server service.
+     */
+    // TODO: rename to onConnected() / add onDisconnected()?
+    public void onReady() {
+        if (DEBUG) Log.d(TAG, "onReady()");
+    }
+
+    /**
+     * Called to receive data from the application that the user was requested auto-fill for.
+     *
+     * @param token unique token identifying the auto-fill session, it should be used when providing
+     * the auto-filled fields.
+     * @param data Arbitrary data supplied by the app through
+     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
+     * May be {@code null} if data has been disabled by the user or device policy.
+     * @param startFlags currently always 0.
+     * @param structure If available, the structure definition of all windows currently
+     * displayed by the app.  May be {@code null} if auto-fill data has been disabled by the user
+     * or device policy; will be an empty stub if the application has disabled auto-fill
+     * by marking its window as secure.
+     */
+    @SuppressWarnings("unused")
+    // TODO: take the factory approach where this method return a session, and move the callback
+    // methods (like autofill()) to the session.
+    public void onNewSession(String token, Bundle data, int startFlags, AssistStructure structure) {
+        if (DEBUG) Log.d(TAG, "onNewSession(): token=" + token);
+    }
+
+    /**
+     * Called when an auto-fill session is finished.
+     */
+    @SuppressWarnings("unused")
+    public void onSessionFinished(String token) {
+        if (DEBUG) Log.d(TAG, "onSessionFinished(): token=" + token);
+    }
+
+    /**
+     * Called during service de-initialization to tell you when the system is shutting the
+     * service down.
+     *
+     * <p> At this point this service may no longer be an active {@link AutoFillService}.
+     */
+    public void onShutdown() {
+        if (DEBUG) Log.d(TAG, "onShutdown()");
+    }
+}
diff --git a/core/java/android/service/autofill/AutoFillServiceInfo.java b/core/java/android/service/autofill/AutoFillServiceInfo.java
new file mode 100644
index 0000000..fe21615
--- /dev/null
+++ b/core/java/android/service/autofill/AutoFillServiceInfo.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.service.autofill;
+
+import android.Manifest;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.RemoteException;
+
+/** @hide */
+public final class AutoFillServiceInfo {
+
+    private static ServiceInfo getServiceInfoOrThrow(ComponentName comp, int userHandle)
+            throws PackageManager.NameNotFoundException {
+        try {
+            final ServiceInfo si =
+                    AppGlobals.getPackageManager().getServiceInfo(comp, 0, userHandle);
+            if (si != null) {
+                return si;
+            }
+        } catch (RemoteException e) {
+        }
+        throw new PackageManager.NameNotFoundException(comp.toString());
+    }
+
+    private String mParseError;
+
+    private ServiceInfo mServiceInfo;
+
+    private  AutoFillServiceInfo(ServiceInfo si) {
+        if (si == null) {
+            mParseError = "Service not available";
+            return;
+        }
+        if (!Manifest.permission.BIND_AUTO_FILL.equals(si.permission)) {
+            mParseError = "Service does not require permission "
+                    + Manifest.permission.BIND_AUTO_FILL;
+            return;
+        }
+
+        mServiceInfo = si;
+    }
+
+    public AutoFillServiceInfo(ComponentName comp, int userHandle)
+            throws PackageManager.NameNotFoundException {
+        this(getServiceInfoOrThrow(comp, userHandle));
+    }
+
+    public String getParseError() {
+        return mParseError;
+    }
+
+    public ServiceInfo getServiceInfo() {
+        return mServiceInfo;
+    }
+}
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
new file mode 100644
index 0000000..2c06234
--- /dev/null
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.os.Bundle;
+
+/**
+ * Intermediator between apps being auto-filled and auto-fill service implementations.
+ *
+ * {@hide}
+ */
+interface IAutoFillManagerService {
+
+    /**
+     * Starts an auto-fill session for the top activities for a given user.
+     *
+     * It's used to start a new session from system affordances.
+     *
+     * @param userId user handle.
+     * @param args the bundle to pass as arguments to the voice interaction session.
+     * @param flags flags indicating optional session behavior.
+     * @param activityToken optional token of activity that needs to be on top.
+     *
+     * @return session token, or null if session was not created (for example, if the activity's
+     *         user does not have an auto-fill service associated with).
+     */
+     // TODO: pass callback providing an onAutoFill() method
+    String startSession(int userId, in Bundle args, int flags, IBinder activityToken);
+
+    /**
+     * Finishes an auto-fill session.
+     *
+     * @param userId user handle.
+     * @param token session token.
+     *
+     * @return true if session existed and was finished.
+     */
+    boolean finishSession(int userId, String token);
+
+}
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
new file mode 100644
index 0000000..73d8d5d
--- /dev/null
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.os.Bundle;
+import android.app.assist.AssistStructure;
+
+/**
+ * @hide
+ */
+oneway interface IAutoFillService {
+    void ready();
+    void newSession(String token, in Bundle data, int flags, in AssistStructure structure);
+    void finishSession(String token);
+    void shutdown();
+}
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 4a956c6..4b272e9 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -22,11 +22,8 @@
 import android.os.Parcelable;
 
 /**
- * Ranking updates from the Ranker.
- *
- * @hide
+ * Ranking updates from the Assistant.
  */
-@SystemApi
 public final class Adjustment implements Parcelable {
     private final String mPackage;
     private final String mKey;
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 8c35901..f639c0d 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -28,7 +28,7 @@
     void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update);
     void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
-            in NotificationRankingUpdate update);
+            in NotificationRankingUpdate update, int reason);
     void onNotificationRankingUpdate(in NotificationRankingUpdate update);
     void onListenerHintsChanged(int hints);
     void onInterruptionFilterChanged(int interruptionFilter);
@@ -38,5 +38,4 @@
     void onNotificationVisibilityChanged(String key, long time, boolean visible);
     void onNotificationClick(String key, long time);
     void onNotificationActionClick(String key, long time, int actionIndex);
-    void onNotificationRemovedReason(String key, long time, int reason);
 }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
new file mode 100644
index 0000000..4e00c64
--- /dev/null
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.annotation.SdkConstant;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+import com.android.internal.os.SomeArgs;
+
+import java.util.List;
+
+/**
+ * A service that helps the user manage notifications.
+ */
+public abstract class NotificationAssistantService extends NotificationListenerService {
+    private static final String TAG = "NotificationAssistants";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE
+            = "android.service.notification.NotificationAssistantService";
+
+    private Handler mHandler;
+
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        mHandler = new MyHandler(getContext().getMainLooper());
+    }
+
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (mWrapper == null) {
+            mWrapper = new NotificationAssistantServiceWrapper();
+        }
+        return mWrapper;
+    }
+
+    /**
+     * A notification was posted by an app. Called before alert.
+     *
+     * @param sbn the new notification
+     * @param importance the initial importance of the notification.
+     * @param user true if the initial importance reflects an explicit user preference.
+     * @return an adjustment or null to take no action, within 100ms.
+     */
+    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+          int importance, boolean user);
+
+    /**
+     * Updates a notification.  N.B. this won’t cause
+     * an existing notification to alert, but might allow a future update to
+     * this notification to alert.
+     *
+     * @param adjustment the adjustment with an explanation
+     */
+    public final void adjustNotification(Adjustment adjustment) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().applyAdjustmentFromAssistantService(mWrapper, adjustment);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    /**
+     * Updates existing notifications. Re-ranking won't occur until all adjustments are applied.
+     * N.B. this won’t cause an existing notification to alert, but might allow a future update to
+     * these notifications to alert.
+     *
+     * @param adjustments a list of adjustments with explanations
+     */
+    public final void adjustNotifications(List<Adjustment> adjustments) {
+        if (!isBound()) return;
+        try {
+            getNotificationInterface().applyAdjustmentsFromAssistantService(mWrapper, adjustments);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
+        @Override
+        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
+                int importance, boolean user) {
+            StatusBarNotification sbn;
+            try {
+                sbn = sbnHolder.get();
+            } catch (RemoteException e) {
+                Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
+                return;
+            }
+
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = sbn;
+            args.argi1 = importance;
+            args.argi2 = user ? 1 : 0;
+            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
+                    args).sendToTarget();
+        }
+    }
+
+    private final class MyHandler extends Handler {
+        public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
+
+        public MyHandler(Looper looper) {
+            super(looper, null, false);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_NOTIFICATION_ENQUEUED: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    StatusBarNotification sbn = (StatusBarNotification) args.arg1;
+                    final int importance = args.argi1;
+                    final boolean user = args.argi2 == 1;
+                    args.recycle();
+                    Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
+                    if (adjustment != null) {
+                        adjustNotification(adjustment);
+                    }
+                } break;
+            }
+        }
+    }
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e606ebf..45011eb 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -77,6 +77,7 @@
  * </p>
  */
 public abstract class NotificationListenerService extends Service {
+
     // TAG = "NotificationListenerService[MySubclass]"
     private final String TAG = NotificationListenerService.class.getSimpleName()
             + "[" + getClass().getSimpleName() + "]";
@@ -146,6 +147,48 @@
     public static final int SUPPRESSED_EFFECT_SCREEN_ON =
             NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
 
+
+    // Notification cancellation reasons
+
+    /** Notification was canceled by the status bar reporting a click. */
+    public static final int REASON_DELEGATE_CLICK = 1;
+    /** Notification was canceled by the status bar reporting a user dismissal. */
+    public static final int REASON_DELEGATE_CANCEL = 2;
+    /** Notification was canceled by the status bar reporting a user dismiss all. */
+    public static final int REASON_DELEGATE_CANCEL_ALL = 3;
+    /** Notification was canceled by the status bar reporting an inflation error. */
+    public static final int REASON_DELEGATE_ERROR = 4;
+    /** Notification was canceled by the package manager modifying the package. */
+    public static final int REASON_PACKAGE_CHANGED = 5;
+    /** Notification was canceled by the owning user context being stopped. */
+    public static final int REASON_USER_STOPPED = 6;
+    /** Notification was canceled by the user banning the package. */
+    public static final int REASON_PACKAGE_BANNED = 7;
+    /** Notification was canceled by the app canceling this specific notification. */
+    public static final int REASON_APP_CANCEL = 8;
+    /** Notification was canceled by the app cancelling all its notifications. */
+    public static final int REASON_APP_CANCEL_ALL = 9;
+    /** Notification was canceled by a listener reporting a user dismissal. */
+    public static final int REASON_LISTENER_CANCEL = 10;
+    /** Notification was canceled by a listener reporting a user dismiss all. */
+    public static final int REASON_LISTENER_CANCEL_ALL = 11;
+    /** Notification was canceled because it was a member of a canceled group. */
+    public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
+    /** Notification was canceled because it was an invisible member of a group. */
+    public static final int REASON_GROUP_OPTIMIZATION = 13;
+    /** Notification was canceled by the device administrator suspending the package. */
+    public static final int REASON_PACKAGE_SUSPENDED = 14;
+    /** Notification was canceled by the owning managed profile being turned off. */
+    public static final int REASON_PROFILE_TURNED_OFF = 15;
+    /** Autobundled summary notification was canceled because its group was unbundled */
+    public static final int REASON_UNAUTOBUNDLED = 16;
+    /** Notification was canceled by the user banning the channel. */
+    public static final int REASON_CHANNEL_BANNED = 17;
+    /** Notification was snoozed. */
+    public static final int REASON_SNOOZED = 18;
+    /** Notification no longer visible because of user switch */
+    public static final int REASON_USER_SWITCH = 19;
+
     /**
      * The full trim of the StatusBarNotification including all its features.
      *
@@ -282,6 +325,32 @@
         onNotificationRemoved(sbn);
     }
 
+
+    /**
+     * Implement this method to learn when notifications are removed and why.
+     * <p>
+     * This might occur because the user has dismissed the notification using system UI (or another
+     * notification listener) or because the app has withdrawn the notification.
+     * <p>
+     * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
+     * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
+     * fields such as {@link android.app.Notification#contentView} and
+     * {@link android.app.Notification#largeIcon}. However, all other fields on
+     * {@link StatusBarNotification}, sufficient to match this call with a prior call to
+     * {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
+     *
+     ** @param sbn A data structure encapsulating at least the original information (tag and id)
+     *            and source (package name) used to post the {@link android.app.Notification} that
+     *            was just removed.
+     * @param rankingMap The current ranking map that can be used to retrieve ranking information
+     *                   for active notifications.
+     * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
+     */
+    public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+            int reason) {
+        onNotificationRemoved(sbn, rankingMap);
+    }
+
     /**
      * Implement this method to learn about when the listener is enabled and connected to
      * the notification manager.  You are safe to call {@link #getActiveNotifications()}
@@ -927,7 +996,7 @@
 
         @Override
         public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
-                NotificationRankingUpdate update) {
+                NotificationRankingUpdate update, int reason) {
             StatusBarNotification sbn;
             try {
                 sbn = sbnHolder.get();
@@ -941,6 +1010,7 @@
                 SomeArgs args = SomeArgs.obtain();
                 args.arg1 = sbn;
                 args.arg2 = mRankingMap;
+                args.arg3 = reason;
                 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED,
                         args).sendToTarget();
             }
@@ -1003,12 +1073,6 @@
                 throws RemoteException {
             // no-op in the listener
         }
-
-        @Override
-        public void onNotificationRemovedReason(String key, long time, int reason)
-                throws RemoteException {
-            // no-op in the listener
-        }
     }
 
     private void applyUpdateLocked(NotificationRankingUpdate update) {
@@ -1413,8 +1477,9 @@
                     SomeArgs args = (SomeArgs) msg.obj;
                     StatusBarNotification sbn = (StatusBarNotification) args.arg1;
                     RankingMap rankingMap = (RankingMap) args.arg2;
+                    int reason = (int) args.arg3;
                     args.recycle();
-                    onNotificationRemoved(sbn, rankingMap);
+                    onNotificationRemoved(sbn, rankingMap, reason);
                 } break;
 
                 case MSG_ON_LISTENER_CONNECTED: {
diff --git a/core/java/android/service/notification/NotificationRankerService.java b/core/java/android/service/notification/NotificationRankerService.java
deleted file mode 100644
index 928d5d8..0000000
--- a/core/java/android/service/notification/NotificationRankerService.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.service.notification;
-
-import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.util.Log;
-import com.android.internal.os.SomeArgs;
-
-import java.util.List;
-
-/**
- * A service that helps the user manage notifications. This class is only used to
- * extend the framework service and may not be implemented by non-framework components.
- * @hide
- */
-@SystemApi
-public abstract class NotificationRankerService extends NotificationListenerService {
-    private static final String TAG = "NotificationRankers";
-
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     */
-    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE
-            = "android.service.notification.NotificationRankerService";
-
-    /** Notification was canceled by the status bar reporting a click. */
-    public static final int REASON_DELEGATE_CLICK = 1;
-
-    /** Notification was canceled by the status bar reporting a user dismissal. */
-    public static final int REASON_DELEGATE_CANCEL = 2;
-
-    /** Notification was canceled by the status bar reporting a user dismiss all. */
-    public static final int REASON_DELEGATE_CANCEL_ALL = 3;
-
-    /** Notification was canceled by the status bar reporting an inflation error. */
-    public static final int REASON_DELEGATE_ERROR = 4;
-
-    /** Notification was canceled by the package manager modifying the package. */
-    public static final int REASON_PACKAGE_CHANGED = 5;
-
-    /** Notification was canceled by the owning user context being stopped. */
-    public static final int REASON_USER_STOPPED = 6;
-
-    /** Notification was canceled by the user banning the package. */
-    public static final int REASON_PACKAGE_BANNED = 7;
-
-    /** Notification was canceled by the app canceling this specific notification. */
-    public static final int REASON_APP_CANCEL = 8;
-
-    /** Notification was canceled by the app cancelling all its notifications. */
-    public static final int REASON_APP_CANCEL_ALL = 9;
-
-    /** Notification was canceled by a listener reporting a user dismissal. */
-    public static final int REASON_LISTENER_CANCEL = 10;
-
-    /** Notification was canceled by a listener reporting a user dismiss all. */
-    public static final int REASON_LISTENER_CANCEL_ALL = 11;
-
-    /** Notification was canceled because it was a member of a canceled group. */
-    public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
-
-    /** Notification was canceled because it was an invisible member of a group. */
-    public static final int REASON_GROUP_OPTIMIZATION = 13;
-
-    /** Notification was canceled by the device administrator suspending the package. */
-    public static final int REASON_PACKAGE_SUSPENDED = 14;
-
-    /** Notification was canceled by the owning managed profile being turned off. */
-    public static final int REASON_PROFILE_TURNED_OFF = 15;
-
-    /** Autobundled summary notification was canceled because its group was unbundled */
-    public static final int REASON_UNAUTOBUNDLED = 16;
-
-    /** Notification was canceled by the user banning the channel. */
-    public static final int REASON_CHANNEL_BANNED = 17;
-
-    /** Notification was snoozed. */
-    public static final int REASON_SNOOZED = 18;
-
-    private Handler mHandler;
-
-    /** @hide */
-    @Override
-    public void registerAsSystemService(Context context, ComponentName componentName,
-            int currentUser)  {
-        throw new UnsupportedOperationException("the ranker lifecycle is managed by the system.");
-    }
-
-    /** @hide */
-    @Override
-    public void unregisterAsSystemService()  {
-        throw new UnsupportedOperationException("the ranker lifecycle is managed by the system.");
-    }
-
-    @Override
-    protected void attachBaseContext(Context base) {
-        super.attachBaseContext(base);
-        mHandler = new MyHandler(getContext().getMainLooper());
-    }
-
-    @Override
-    public final IBinder onBind(Intent intent) {
-        if (mWrapper == null) {
-            mWrapper = new NotificationRankingServiceWrapper();
-        }
-        return mWrapper;
-    }
-
-    /**
-     * A notification was posted by an app. Called before alert.
-     *
-     * @param sbn the new notification
-     * @param importance the initial importance of the notification.
-     * @param user true if the initial importance reflects an explicit user preference.
-     * @return an adjustment or null to take no action, within 100ms.
-     */
-    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
-          int importance, boolean user);
-
-    /**
-     * The visibility of a notification has changed.
-     *
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     * @param visible true if the notification became visible, false if hidden.
-     */
-    public void onNotificationVisibilityChanged(String key, long time, boolean visible)
-    {
-        // Do nothing, Override this to collect visibility statistics.
-    }
-
-    /**
-     * The user clicked on a notification.
-     *
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     */
-    public void onNotificationClick(String key, long time)
-    {
-        // Do nothing, Override this to collect click statistics
-    }
-
-    /**
-     * The user clicked on a notification action.
-     *
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     * @param actionIndex the index of the action button that was pressed.
-     */
-    public void onNotificationActionClick(String key, long time, int actionIndex)
-    {
-        // Do nothing, Override this to collect action button click statistics
-    }
-
-    /**
-     * A notification was removed.
-
-     * @param key the notification key
-     * @param time milliseconds since midnight, January 1, 1970 UTC.
-     * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
-     */
-    public void onNotificationRemoved(String key, long time, int reason) {
-        // Do nothing, Override this to collect dismissal statistics
-    }
-
-    /**
-     * Updates a notification.  N.B. this won’t cause
-     * an existing notification to alert, but might allow a future update to
-     * this notification to alert.
-     *
-     * @param adjustment the adjustment with an explanation
-     */
-    public final void adjustNotification(Adjustment adjustment) {
-        if (!isBound()) return;
-        try {
-            getNotificationInterface().applyAdjustmentFromRankerService(mWrapper, adjustment);
-        } catch (android.os.RemoteException ex) {
-            Log.v(TAG, "Unable to contact notification manager", ex);
-        }
-    }
-
-    /**
-     * Updates existing notifications. Re-ranking won't occur until all adjustments are applied.
-     * N.B. this won’t cause an existing notification to alert, but might allow a future update to
-     * these notifications to alert.
-     *
-     * @param adjustments a list of adjustments with explanations
-     */
-    public final void adjustNotifications(List<Adjustment> adjustments) {
-        if (!isBound()) return;
-        try {
-            getNotificationInterface().applyAdjustmentsFromRankerService(mWrapper, adjustments);
-        } catch (android.os.RemoteException ex) {
-            Log.v(TAG, "Unable to contact notification manager", ex);
-        }
-    }
-
-    private class NotificationRankingServiceWrapper extends NotificationListenerWrapper {
-        @Override
-        public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder,
-                int importance, boolean user) {
-            StatusBarNotification sbn;
-            try {
-                sbn = sbnHolder.get();
-            } catch (RemoteException e) {
-                Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
-                return;
-            }
-
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = sbn;
-            args.argi1 = importance;
-            args.argi2 = user ? 1 : 0;
-            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
-                    args).sendToTarget();
-        }
-
-        @Override
-        public void onNotificationVisibilityChanged(String key, long time, boolean visible) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = key;
-            args.arg2 = time;
-            args.argi1 = visible ? 1 : 0;
-            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_VISIBILITY_CHANGED,
-                    args).sendToTarget();
-        }
-
-        @Override
-        public void onNotificationClick(String key, long time) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = key;
-            args.arg2 = time;
-            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_CLICK,
-                    args).sendToTarget();
-        }
-
-        @Override
-        public void onNotificationActionClick(String key, long time, int actionIndex) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = key;
-            args.arg2 = time;
-            args.argi1 = actionIndex;
-            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ACTION_CLICK,
-                    args).sendToTarget();
-        }
-
-        @Override
-        public void onNotificationRemovedReason(String key, long time, int reason) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = key;
-            args.arg2 = time;
-            args.argi1 = reason;
-            mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_REMOVED_REASON,
-                    args).sendToTarget();
-        }
-    }
-
-    private final class MyHandler extends Handler {
-        public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
-        public static final int MSG_ON_NOTIFICATION_VISIBILITY_CHANGED = 2;
-        public static final int MSG_ON_NOTIFICATION_CLICK = 3;
-        public static final int MSG_ON_NOTIFICATION_ACTION_CLICK = 4;
-        public static final int MSG_ON_NOTIFICATION_REMOVED_REASON = 5;
-
-        public MyHandler(Looper looper) {
-            super(looper, null, false);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_ON_NOTIFICATION_ENQUEUED: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    StatusBarNotification sbn = (StatusBarNotification) args.arg1;
-                    final int importance = args.argi1;
-                    final boolean user = args.argi2 == 1;
-                    args.recycle();
-                    Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
-                    if (adjustment != null) {
-                        adjustNotification(adjustment);
-                    }
-                } break;
-
-                case MSG_ON_NOTIFICATION_VISIBILITY_CHANGED: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    final String key = (String) args.arg1;
-                    final long time = (long) args.arg2;
-                    final boolean visible = args.argi1 == 1;
-                    args.recycle();
-                    onNotificationVisibilityChanged(key, time, visible);
-                } break;
-
-                case MSG_ON_NOTIFICATION_CLICK: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    final String key = (String) args.arg1;
-                    final long time = (long) args.arg2;
-                    args.recycle();
-                    onNotificationClick(key, time);
-                } break;
-
-                case MSG_ON_NOTIFICATION_ACTION_CLICK: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    final String key = (String) args.arg1;
-                    final long time = (long) args.arg2;
-                    final int actionIndex = args.argi1;
-                    args.recycle();
-                    onNotificationActionClick(key, time, actionIndex);
-                } break;
-
-                case MSG_ON_NOTIFICATION_REMOVED_REASON: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    final String key = (String) args.arg1;
-                    final long time = (long) args.arg2;
-                    final int reason = args.argi1;
-                    args.recycle();
-                    onNotificationRemoved(key, time, reason);
-                } break;
-            }
-        }
-    }
-}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index be0b47c..dfb6b86 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -17,6 +17,7 @@
 package android.service.notification;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -42,25 +43,21 @@
     private final Notification notification;
     private final UserHandle user;
     private final long postTime;
+    private final NotificationChannel channel;
 
     private Context mContext; // used for inflation & icon expansion
 
     /** @hide */
-    public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
-            int initialPid, int score, Notification notification, UserHandle user) {
-        this(pkg, opPkg, id, tag, uid, initialPid, score, notification, user,
-                System.currentTimeMillis());
-    }
-
-    /** @hide */
-    public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
-            int initialPid, Notification notification, UserHandle user, String overrideGroupKey,
-            long postTime) {
+    public StatusBarNotification(String pkg, String opPkg, NotificationChannel channel, int id,
+            String tag, int uid, int initialPid, Notification notification, UserHandle user,
+            String overrideGroupKey, long postTime) {
         if (pkg == null) throw new NullPointerException();
         if (notification == null) throw new NullPointerException();
+        if (channel == null) throw new IllegalArgumentException();
 
         this.pkg = pkg;
         this.opPkg = opPkg;
+        this.channel = channel;
         this.id = id;
         this.tag = tag;
         this.uid = uid;
@@ -73,6 +70,7 @@
         this.groupKey = groupKey();
     }
 
+    @Deprecated
     public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user,
             long postTime) {
@@ -90,6 +88,7 @@
         this.postTime = postTime;
         this.key = key();
         this.groupKey = groupKey();
+        this.channel = null;
     }
 
     public StatusBarNotification(Parcel in) {
@@ -113,6 +112,7 @@
         }
         this.key = key();
         this.groupKey = groupKey();
+        this.channel = NotificationChannel.CREATOR.createFromParcel(in);
     }
 
     private String key() {
@@ -182,6 +182,7 @@
         } else {
             out.writeInt(0);
         }
+        this.channel.writeToParcel(out, flags);
     }
 
     public int describeContents() {
@@ -208,14 +209,14 @@
     public StatusBarNotification cloneLight() {
         final Notification no = new Notification();
         this.notification.cloneInto(no, false); // light copy
-        return new StatusBarNotification(this.pkg, this.opPkg,
+        return new StatusBarNotification(this.pkg, this.opPkg, this.channel,
                 this.id, this.tag, this.uid, this.initialPid,
                 no, this.user, this.overrideGroupKey, this.postTime);
     }
 
     @Override
     public StatusBarNotification clone() {
-        return new StatusBarNotification(this.pkg, this.opPkg,
+        return new StatusBarNotification(this.pkg, this.opPkg, this.channel,
                 this.id, this.tag, this.uid, this.initialPid,
                 this.notification.clone(), this.user, this.overrideGroupKey, this.postTime);
     }
@@ -335,6 +336,13 @@
     }
 
     /**
+     * Returns the channel this notification was posted to.
+     */
+    public NotificationChannel getNotificationChannel() {
+        return channel;
+    }
+
+    /**
      * @hide
      */
     public Context getPackageContext(Context context) {
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
index ec852e8..85d10f1 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -142,11 +142,17 @@
      * @see #getInflatedId()
      * @attr ref android.R.styleable#ViewStub_inflatedId
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl = "setInflatedIdAsync")
     public void setInflatedId(@IdRes int inflatedId) {
         mInflatedId = inflatedId;
     }
 
+    /** @hide **/
+    public Runnable setInflatedIdAsync(@IdRes int inflatedId) {
+        mInflatedId = inflatedId;
+        return null;
+    }
+
     /**
      * Returns the layout resource that will be used by {@link #setVisibility(int)} or
      * {@link #inflate()} to replace this StubbedView
@@ -176,11 +182,17 @@
      * @see #inflate()
      * @attr ref android.R.styleable#ViewStub_layout
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl = "setLayoutResourceAsync")
     public void setLayoutResource(@LayoutRes int layoutResource) {
         mLayoutResource = layoutResource;
     }
 
+    /** @hide **/
+    public Runnable setLayoutResourceAsync(@LayoutRes int layoutResource) {
+        mLayoutResource = layoutResource;
+        return null;
+    }
+
     /**
      * Set {@link LayoutInflater} to use in {@link #inflate()}, or {@code null}
      * to use the default.
@@ -220,7 +232,7 @@
      * @see #inflate() 
      */
     @Override
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl = "setVisibilityAsync")
     public void setVisibility(int visibility) {
         if (mInflatedViewRef != null) {
             View view = mInflatedViewRef.get();
@@ -237,6 +249,43 @@
         }
     }
 
+    /** @hide **/
+    public Runnable setVisibilityAsync(int visibility) {
+        if (visibility == VISIBLE || visibility == INVISIBLE) {
+            ViewGroup parent = (ViewGroup) getParent();
+            return new ViewReplaceRunnable(inflateViewNoAdd(parent));
+        } else {
+            return null;
+        }
+    }
+
+    private View inflateViewNoAdd(ViewGroup parent) {
+        final LayoutInflater factory;
+        if (mInflater != null) {
+            factory = mInflater;
+        } else {
+            factory = LayoutInflater.from(mContext);
+        }
+        final View view = factory.inflate(mLayoutResource, parent, false);
+
+        if (mInflatedId != NO_ID) {
+            view.setId(mInflatedId);
+        }
+        return view;
+    }
+
+    private void replaceSelfWithView(View view, ViewGroup parent) {
+        final int index = parent.indexOfChild(this);
+        parent.removeViewInLayout(this);
+
+        final ViewGroup.LayoutParams layoutParams = getLayoutParams();
+        if (layoutParams != null) {
+            parent.addView(view, index, layoutParams);
+        } else {
+            parent.addView(view, index);
+        }
+    }
+
     /**
      * Inflates the layout resource identified by {@link #getLayoutResource()}
      * and replaces this StubbedView in its parent by the inflated layout resource.
@@ -250,31 +299,10 @@
         if (viewParent != null && viewParent instanceof ViewGroup) {
             if (mLayoutResource != 0) {
                 final ViewGroup parent = (ViewGroup) viewParent;
-                final LayoutInflater factory;
-                if (mInflater != null) {
-                    factory = mInflater;
-                } else {
-                    factory = LayoutInflater.from(mContext);
-                }
-                final View view = factory.inflate(mLayoutResource, parent,
-                        false);
+                final View view = inflateViewNoAdd(parent);
+                replaceSelfWithView(view, parent);
 
-                if (mInflatedId != NO_ID) {
-                    view.setId(mInflatedId);
-                }
-
-                final int index = parent.indexOfChild(this);
-                parent.removeViewInLayout(this);
-
-                final ViewGroup.LayoutParams layoutParams = getLayoutParams();
-                if (layoutParams != null) {
-                    parent.addView(view, index, layoutParams);
-                } else {
-                    parent.addView(view, index);
-                }
-
-                mInflatedViewRef = new WeakReference<View>(view);
-
+                mInflatedViewRef = new WeakReference<>(view);
                 if (mInflateListener != null) {
                     mInflateListener.onInflate(this, view);
                 }
@@ -317,4 +345,18 @@
          */
         void onInflate(ViewStub stub, View inflated);
     }
+
+    /** @hide **/
+    public class ViewReplaceRunnable implements Runnable {
+        public final View view;
+
+        ViewReplaceRunnable(View view) {
+            this.view = view;
+        }
+
+        @Override
+        public void run() {
+            replaceSelfWithView(view, (ViewGroup) getParent());
+        }
+    }
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 8a9bb33..4195d91 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -509,6 +509,11 @@
          * Notifies window manager that {@link #isShowingDreamLw} has changed.
          */
         void notifyShowingDreamChanged();
+
+        /**
+         * Notifies window manager that {@link #isKeyguardTrustedLw} has changed.
+         */
+        void notifyKeyguardTrustedChanged();
     }
 
     public interface PointerEventListener {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index b2a77d0..18ce260 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -58,6 +58,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.widget.AdapterView.OnItemClickListener;
 
 import com.android.internal.R;
@@ -1456,6 +1457,13 @@
                     if (endAction == null) {
                         return ACTION_NOOP;
                     } else {
+                        // Special case view stub
+                        if (endAction instanceof ViewStub.ViewReplaceRunnable) {
+                            root.createTree();
+                            // Replace child tree
+                            root.findViewTreeById(viewId).replaceView(
+                                    ((ViewStub.ViewReplaceRunnable) endAction).view);
+                        }
                         return new RunnableAction(endAction);
                     }
                 }
@@ -1581,16 +1589,26 @@
             if ((target == null) || !(target.mRoot instanceof ViewGroup)) {
                 return ACTION_NOOP;
             }
+            final ViewGroup targetVg = (ViewGroup) target.mRoot;
             if (nestedViews == null) {
                 // Clear all children when nested views omitted
                 target.mChildren = null;
-                return this;
+                return new RuntimeAction() {
+                    @Override
+                    public void apply(View root, ViewGroup rootParent, OnClickHandler handler)
+                            throws ActionException {
+                        targetVg.removeAllViews();
+                    }
+                };
             } else {
                 // Inflate nested views and perform all the async tasks for the child remoteView.
                 final Context context = root.mRoot.getContext();
                 final AsyncApplyTask task = nestedViews.getAsyncApplyTask(
-                        context, (ViewGroup) target.mRoot, null, handler);
+                        context, targetVg, null, handler);
                 final ViewTree tree = task.doInBackground();
+                if (tree == null) {
+                    throw new ActionException(task.mError);
+                }
 
                 // Update the global view tree, so that next call to findViewTreeById
                 // goes through the subtree as well.
@@ -1600,10 +1618,8 @@
 
                     @Override
                     public void apply(View root, ViewGroup rootParent, OnClickHandler handler) throws ActionException {
-                        // This view will exist as we have already made sure
-                        final ViewGroup target = (ViewGroup) root.findViewById(viewId);
                         task.onPostExecute(tree);
-                        target.addView(task.mResult);
+                        targetVg.addView(task.mResult);
                     }
                 };
             }
@@ -3360,7 +3376,7 @@
                     int count = mRV.mActions.size();
                     mActions = new Action[count];
                     for (int i = 0; i < count && !isCancelled(); i++) {
-                        // TODO: check if isCanclled in nested views.
+                        // TODO: check if isCancelled in nested views.
                         mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler);
                     }
                 } else {
@@ -3629,7 +3645,7 @@
      * and can be searched.
      */
     private static class ViewTree {
-        private final View mRoot;
+        private View mRoot;
 
         private ArrayList<ViewTree> mChildren;
 
@@ -3643,7 +3659,7 @@
             }
 
             mChildren = new ArrayList<>();
-            if (mRoot instanceof ViewGroup && mRoot.isRootNamespace()) {
+            if (mRoot instanceof ViewGroup) {
                 ViewGroup vg = (ViewGroup) mRoot;
                 int count = vg.getChildCount();
                 for (int i = 0; i < count; i++) {
@@ -3668,6 +3684,12 @@
             return null;
         }
 
+        public void replaceView(View v) {
+            mRoot = v;
+            mChildren = null;
+            createTree();
+        }
+
         public View findViewById(int id) {
             if (mChildren == null) {
                 return mRoot.findViewById(id);
@@ -3685,6 +3707,12 @@
         }
 
         private void addViewChild(View v) {
+            // ViewTree only contains Views which can be found using findViewById.
+            // If isRootNamespace is true, this view is skipped.
+            // @see ViewGroup#findViewTraversal(int)
+            if (v.isRootNamespace()) {
+                return;
+            }
             final ViewTree target;
 
             // If the view has a valid id, i.e., if can be found using findViewById, add it to the
@@ -3697,7 +3725,7 @@
                 target = this;
             }
 
-            if (v instanceof ViewGroup && v.isRootNamespace()) {
+            if (v instanceof ViewGroup) {
                 if (target.mChildren == null) {
                     target.mChildren = new ArrayList<>();
                     ViewGroup vg = (ViewGroup) v;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 3b6073a..d8f7907 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -70,7 +70,7 @@
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.TargetInfo;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.google.android.collect.Lists;
 
 import java.io.File;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 1e26c92..72a40b7 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -71,7 +71,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.widget.ResolverDrawerLayout;
 
 import java.util.ArrayList;
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index ef725da..a94f308 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -19,7 +19,7 @@
 import android.os.Build;
 import android.view.View;
 
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 /**
  * Log all the things.
diff --git a/core/java/com/android/internal/os/AppFuseMount.java b/core/java/com/android/internal/os/AppFuseMount.java
new file mode 100644
index 0000000..b392186
--- /dev/null
+++ b/core/java/com/android/internal/os/AppFuseMount.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import java.io.File;
+
+public class AppFuseMount implements Parcelable {
+    final public File mountPoint;
+    final public ParcelFileDescriptor fd;
+
+    public AppFuseMount(File mountPoint, ParcelFileDescriptor fd) {
+        this.mountPoint = mountPoint;
+        this.fd = fd;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(this.mountPoint.getPath());
+        dest.writeParcelable(fd, flags);
+    }
+
+    public static final Parcelable.Creator<AppFuseMount> CREATOR =
+            new Parcelable.Creator<AppFuseMount>() {
+        @Override
+        public AppFuseMount createFromParcel(Parcel in) {
+            return new AppFuseMount(new File(in.readString()), in.readParcelable(null));
+        }
+
+        @Override
+        public AppFuseMount[] newArray(int size) {
+            return new AppFuseMount[size];
+        }
+    };
+}
diff --git a/core/java/com/android/internal/os/TransferPipe.java b/core/java/com/android/internal/os/TransferPipe.java
index e76b395..f904150 100644
--- a/core/java/com/android/internal/os/TransferPipe.java
+++ b/core/java/com/android/internal/os/TransferPipe.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.os;
 
+import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -32,13 +33,13 @@
 /**
  * Helper for transferring data through a pipe from a client app.
  */
-public final class TransferPipe implements Runnable {
+public final class TransferPipe implements Runnable, Closeable {
     static final String TAG = "TransferPipe";
     static final boolean DEBUG = false;
 
     static final long DEFAULT_TIMEOUT = 5000;  // 5 seconds
 
-    final Thread mThread;;
+    final Thread mThread;
     final ParcelFileDescriptor[] mFds;
 
     FileDescriptor mOutFd;
@@ -54,8 +55,13 @@
     }
 
     public TransferPipe() throws IOException {
+        this(null);
+    }
+
+    public TransferPipe(String bufferPrefix) throws IOException {
         mThread = new Thread(this, "TransferPipe");
         mFds = ParcelFileDescriptor.createPipe();
+        mBufferPrefix = bufferPrefix;
     }
 
     ParcelFileDescriptor getReadFd() {
@@ -70,6 +76,11 @@
         mBufferPrefix = prefix;
     }
 
+    public static void dumpAsync(IBinder binder, FileDescriptor out, String[] args)
+            throws IOException, RemoteException {
+        goDump(binder, out, args);
+    }
+
     static void go(Caller caller, IInterface iface, FileDescriptor out,
             String prefix, String[] args) throws IOException, RemoteException {
         go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT);
@@ -86,12 +97,9 @@
             return;
         }
 
-        TransferPipe tp = new TransferPipe();
-        try {
+        try (TransferPipe tp = new TransferPipe()) {
             caller.go(iface, tp.getWriteFd().getFileDescriptor(), prefix, args);
             tp.go(out, timeout);
-        } finally {
-            tp.kill();
         }
     }
 
@@ -111,12 +119,9 @@
             return;
         }
 
-        TransferPipe tp = new TransferPipe();
-        try {
+        try (TransferPipe tp = new TransferPipe()) {
             binder.dumpAsync(tp.getWriteFd().getFileDescriptor(), args);
             tp.go(out, timeout);
-        } finally {
-            tp.kill();
         }
     }
 
@@ -173,6 +178,11 @@
         }
     }
 
+    @Override
+    public void close() {
+        kill();
+    }
+
     public void kill() {
         synchronized (this) {
             closeFd(0);
diff --git a/core/java/com/android/internal/policy/EmergencyAffordanceManager.java b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
index bed7c1ba..eb75bd4 100644
--- a/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
+++ b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
+import android.os.UserHandle;
 import android.provider.Settings;
 
 /**
@@ -72,7 +73,7 @@
         Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY);
         intent.setData(getPhoneUri(context));
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
+        context.startActivityAsUser(intent, UserHandle.CURRENT);
     }
 
     /**
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 7387b29..886c0e6 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -267,17 +267,17 @@
 
     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
     if (interfaceName) {
-        hardware::Parcel *parcel =
-            JHwParcel::GetNativeContext(env, thiz)->getParcel();
-
-        status_t err = parcel->writeInterfaceToken(
-                String16(
-                    reinterpret_cast<const char16_t *>(interfaceName),
-                    env->GetStringLength(interfaceNameObj)));
+        String16 nameCopy(
+                reinterpret_cast<const char16_t *>(interfaceName),
+                env->GetStringLength(interfaceNameObj));
 
         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
         interfaceName = NULL;
 
+        hardware::Parcel *parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+        status_t err = parcel->writeInterfaceToken(nameCopy);
         signalExceptionForError(env, err);
     }
 }
@@ -294,17 +294,18 @@
 
     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
     if (interfaceName) {
-        hardware::Parcel *parcel =
-            JHwParcel::GetNativeContext(env, thiz)->getParcel();
-
-        bool valid = parcel->enforceInterface(
-                String16(
-                    reinterpret_cast<const char16_t *>(interfaceName),
-                    env->GetStringLength(interfaceNameObj)));
+        String16 interfaceNameCopy(
+                reinterpret_cast<const char16_t *>(interfaceName),
+                env->GetStringLength(interfaceNameObj));
 
         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
         interfaceName = NULL;
 
+        hardware::Parcel *parcel =
+            JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+        bool valid = parcel->enforceInterface(interfaceNameCopy);
+
         if (!valid) {
             jniThrowException(
                     env,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index bba3d76..fc85b4b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -628,6 +628,12 @@
     }
   } else if (pid > 0) {
     // the parent process
+
+    // We blocked SIGCHLD prior to a fork, we unblock it here.
+    if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
+      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
+      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+    }
   }
   return pid;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4eebea6..3dea051 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2323,6 +2323,13 @@
     <permission android:name="android.permission.BIND_VOICE_INTERACTION"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by a {@link android.service.autofill.AutoFillService},
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_AUTO_FILL"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
@@ -2937,11 +2944,11 @@
         android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
-         android.service.notification.NotificationRankerService         to ensure that only the system can bind to it.
+         android.service.notification.NotificationAssistantService to ensure that only the system
+         can bind to it.
          <p>Protection level: signature
-         @hide This is not a third-party API (intended for system apps). -->
     -->
-    <permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
+    <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
         android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
@@ -3118,6 +3125,11 @@
     <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to manage auto-fill sessions.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.MANAGE_AUTO_FILL"
+        android:protectionLevel="signature" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/values-watch/colors_material.xml b/core/res/res/values-watch/colors_material.xml
index 18bfd4d..1456976 100644
--- a/core/res/res/values-watch/colors_material.xml
+++ b/core/res/res/values-watch/colors_material.xml
@@ -14,13 +14,13 @@
      limitations under the License.
 -->
 <resources>
-    <color name="background_material_dark">#ff232e33</color>
-    <color name="background_floating_material_dark">#ff3e5059</color>
+    <color name="background_material_dark">#232E33</color>
+    <color name="background_floating_material_dark">#3E5059</color>
 
-    <color name="accent_material_700">#ff2e4978</color>
-    <color name="accent_material_light">#ff4285f4</color>
-    <color name="accent_material_dark">#ff5e97f6</color>
-    <color name="accent_material_50">#ffd0def7</color>
+    <color name="accent_material_700">#5385DB</color>
+    <color name="accent_material_light">#75A4F5</color>
+    <color name="accent_material_dark">#5E97F6</color>
+    <color name="accent_material_50">#93B7F5</color>
 
     <color name="primary_material_dark">#4D4D4D</color>
 
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 89691e9..8f0350a 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -28,10 +28,10 @@
     <color name="tertiary_device_default_settings">@color/tertiary_material_settings</color>
     <color name="quaternary_device_default_settings">@color/quaternary_material_settings</color>
 
-    <color name="accent_device_default_700">@color/material_deep_teal_700</color>
+    <color name="accent_device_default_700">@color/accent_material_700</color>
     <color name="accent_device_default_light">@color/accent_material_light</color>
     <color name="accent_device_default_dark">@color/accent_material_dark</color>
-    <color name="accent_device_default_50">@color/material_deep_teal_50</color>
+    <color name="accent_device_default_50">@color/accent_material_50</color>
 
     <color name="background_device_default_dark">@color/background_material_dark</color>
     <color name="background_device_default_light">@color/background_material_light</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 44bc3ff..7005afe 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1919,6 +1919,12 @@
          mirror the content of the default display. -->
     <bool name="config_localDisplaysMirrorContent">true</bool>
 
+    <!-- The default mode for the default display. One of the following values (See Display.java):
+             0 - COLOR_MODE_DEFAULT
+             7 - COLOR_MODE_SRGB
+    -->
+    <integer name="config_defaultDisplayDefaultColorMode">0</integer>
+
     <!-- When true use the linux /dev/input/event subsystem to detect the switch changes
          on the headphone/microphone jack. When false use the older uevent framework. -->
     <bool name="config_useDevInputEventForAudioJack">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3be98b6..6c0dc35 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -309,6 +309,7 @@
   <java-symbol type="bool" name="config_supportsMultiWindow" />
   <java-symbol type="bool" name="config_guestUserEphemeral" />
   <java-symbol type="bool" name="config_localDisplaysMirrorContent" />
+  <java-symbol type="integer" name="config_defaultDisplayDefaultColorMode" />
   <java-symbol type="bool" name="config_enableAppWidgetService" />
   <java-symbol type="string" name="config_defaultPictureInPictureScreenEdgeInsets" />
   <java-symbol type="string" name="config_defaultPictureInPictureSize" />
diff --git a/core/tests/coretests/res/layout/remote_view_host.xml b/core/tests/coretests/res/layout/remote_view_host.xml
index 19d0a73..6809508 100644
--- a/core/tests/coretests/res/layout/remote_view_host.xml
+++ b/core/tests/coretests/res/layout/remote_view_host.xml
@@ -19,7 +19,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-</LinearLayout>
+    android:layout_height="match_parent" />
diff --git a/core/tests/coretests/res/layout/remote_views_text.xml b/core/tests/coretests/res/layout/remote_views_text.xml
new file mode 100644
index 0000000..a265d2e
--- /dev/null
+++ b/core/tests/coretests/res/layout/remote_views_text.xml
@@ -0,0 +1,21 @@
+<?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
+  -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
diff --git a/core/tests/coretests/res/layout/remote_views_viewstub.xml b/core/tests/coretests/res/layout/remote_views_viewstub.xml
new file mode 100644
index 0000000..d532749
--- /dev/null
+++ b/core/tests/coretests/res/layout/remote_views_viewstub.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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="match_parent"
+             android:layout_height="0dp"
+             android:layout_weight="1">
+
+    <ViewStub android:id="@+id/viewStub"
+              android:inflatedId="@+id/stub_inflated"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent" />
+</FrameLayout>
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 7ba46be..b6b0e68 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -20,11 +20,13 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.os.Parcel;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
+import android.view.ViewGroup;
 
 import com.android.frameworks.coretests.R;
 
@@ -38,6 +40,10 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+
 /**
  * Tests for RemoteViews.
  */
@@ -166,4 +172,164 @@
         parcel.recycle();
         return size;
     }
+
+    @Test
+    public void asyncApply_fail() throws Exception {
+        RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_test_bad_1);
+        ViewAppliedListener listener = new ViewAppliedListener();
+        views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener);
+
+        boolean exceptionThrown = false;
+        try {
+            listener.waitAndGetView();
+        } catch (Exception e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+    }
+
+    @Test
+    public void asyncApply() throws Exception {
+        RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
+        views.setTextViewText(R.id.text, "Dummy");
+
+        View syncView = views.apply(mContext, mContainer);
+
+        ViewAppliedListener listener = new ViewAppliedListener();
+        views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener);
+        View asyncView = listener.waitAndGetView();
+
+        verifyViewTree(syncView, asyncView, "Dummy");
+    }
+
+    @Test
+    public void asyncApply_viewStub() throws Exception {
+        RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_viewstub);
+        views.setInt(R.id.viewStub, "setLayoutResource", R.layout.remote_views_text);
+        // This will cause the view to be inflated
+        views.setViewVisibility(R.id.viewStub, View.INVISIBLE);
+        views.setTextViewText(R.id.stub_inflated, "Dummy");
+
+        View syncView = views.apply(mContext, mContainer);
+
+        ViewAppliedListener listener = new ViewAppliedListener();
+        views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener);
+        View asyncView = listener.waitAndGetView();
+
+        verifyViewTree(syncView, asyncView, "Dummy");
+    }
+
+    @Test
+    public void asyncApply_nestedViews() throws Exception {
+        RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_host);
+        views.removeAllViews(R.id.container);
+        views.addView(R.id.container, createViewChained(1, "row1-c1", "row1-c2", "row1-c3"));
+        views.addView(R.id.container, createViewChained(5, "row2-c1", "row2-c2"));
+        views.addView(R.id.container, createViewChained(2, "row3-c1", "row3-c2"));
+
+        View syncView = views.apply(mContext, mContainer);
+
+        ViewAppliedListener listener = new ViewAppliedListener();
+        views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener);
+        View asyncView = listener.waitAndGetView();
+
+        verifyViewTree(syncView, asyncView,
+                "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2", "row3-c1", "row3-c2");
+    }
+
+    @Test
+    public void asyncApply_viewstub_nestedViews() throws Exception {
+        RemoteViews viewstub = new RemoteViews(mPackage, R.layout.remote_views_viewstub);
+        viewstub.setInt(R.id.viewStub, "setLayoutResource", R.layout.remote_view_host);
+        // This will cause the view to be inflated
+        viewstub.setViewVisibility(R.id.viewStub, View.INVISIBLE);
+        viewstub.addView(R.id.stub_inflated, createViewChained(1, "row1-c1", "row1-c2", "row1-c3"));
+
+        RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_host);
+        views.removeAllViews(R.id.container);
+        views.addView(R.id.container, viewstub);
+        views.addView(R.id.container, createViewChained(5, "row2-c1", "row2-c2"));
+
+        View syncView = views.apply(mContext, mContainer);
+
+        ViewAppliedListener listener = new ViewAppliedListener();
+        views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener);
+        View asyncView = listener.waitAndGetView();
+
+        verifyViewTree(syncView, asyncView, "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2");
+    }
+
+    private RemoteViews createViewChained(int depth, String... texts) {
+        RemoteViews result = new RemoteViews(mPackage, R.layout.remote_view_host);
+
+        // Create depth
+        RemoteViews parent = result;
+        while(depth > 0) {
+            depth--;
+            RemoteViews child = new RemoteViews(mPackage, R.layout.remote_view_host);
+            parent.addView(R.id.container, child);
+            parent = child;
+        }
+
+        // Add texts
+        for (String text : texts) {
+            RemoteViews child = new RemoteViews(mPackage, R.layout.remote_views_text);
+            child.setTextViewText(R.id.text, text);
+            parent.addView(R.id.container, child);
+        }
+        return result;
+    }
+
+    private void verifyViewTree(View v1, View v2, String... texts) {
+        ArrayList<String> expectedTexts = new ArrayList<>(Arrays.asList(texts));
+        verifyViewTreeRecur(v1, v2, expectedTexts);
+        // Verify that all expected texts were found
+        assertEquals(0, expectedTexts.size());
+    }
+
+    private void verifyViewTreeRecur(View v1, View v2, ArrayList<String> expectedTexts) {
+        assertEquals(v1.getClass(), v2.getClass());
+
+        if (v1 instanceof TextView) {
+            String text = ((TextView) v1).getText().toString();
+            assertEquals(text, ((TextView) v2).getText().toString());
+            // Verify that the text was one of the expected texts and remove it from the list
+            assertTrue(expectedTexts.remove(text));
+        } else if (v1 instanceof ViewGroup) {
+            ViewGroup vg1 = (ViewGroup) v1;
+            ViewGroup vg2 = (ViewGroup) v2;
+            assertEquals(vg1.getChildCount(), vg2.getChildCount());
+            for (int i = vg1.getChildCount() - 1; i >= 0; i--) {
+                verifyViewTreeRecur(vg1.getChildAt(i), vg2.getChildAt(i), expectedTexts);
+            }
+        }
+    }
+
+    private class ViewAppliedListener implements RemoteViews.OnViewAppliedListener {
+
+        private final CountDownLatch mLatch = new CountDownLatch(1);
+        private View mView;
+        private Exception mError;
+
+        @Override
+        public void onViewApplied(View v) {
+            mView = v;
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onError(Exception e) {
+            mError = e;
+            mLatch.countDown();
+        }
+
+        public View waitAndGetView() throws Exception {
+            mLatch.await();
+
+            if (mError != null) {
+                throw new Exception(mError);
+            }
+            return mView;
+        }
+    }
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 4fc7892..5e59a64 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.IBinder;
 import android.os.Looper;
@@ -630,7 +631,7 @@
                 if (!mConnectedAtLeastOnce) {
                     mConnectedAtLeastOnce = true;
                     try {
-                        q.put(IKeyChainService.Stub.asInterface(service));
+                        q.put(IKeyChainService.Stub.asInterface(Binder.allowBlocking(service)));
                     } catch (InterruptedException e) {
                         // will never happen, since the queue starts with one available slot
                     }
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 7c97e77..5e21dfc 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -738,7 +738,7 @@
 void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
         const SkPaint& paint, const SkPath& path, size_t start, size_t end) {
     const int N = end - start;
-    SkAutoSMalloc<1024> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform)));
+    SkAutoSTMalloc<1024, uint8_t> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform)));
     SkRSXform* xform = (SkRSXform*)storage.get();
     uint16_t* glyphs = (uint16_t*)(xform + N);
     SkPathMeasure meas(path, false);
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index a204d5c..6973209 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -215,7 +215,7 @@
 static void DrawRRectShadows(const SkRect& casterRect, SkScalar casterCornerRadius,
         SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterAlpha, SkScalar casterZValue,
         SkScalar scaleFactor, SkCanvas* canvas) {
-    SkASSERT(cornerRadius >= 0.0f);
+    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;
@@ -387,7 +387,7 @@
 static void DrawRRectShadowsWithClip(const SkRect& casterRect, SkScalar casterCornerRadius,
         SkScalar ambientAlpha, SkScalar spotAlpha, SkScalar casterZValue, SkScalar scaleFactor,
         const SkRRect& clipRR, SkCanvas* canvas) {
-    SkASSERT(cornerRadius >= 0.0f);
+    SkASSERT(casterCornerRadius >= 0.0f);
 
     const bool isOval = casterCornerRadius >= std::max(SkScalarHalf(casterRect.width()),
             SkScalarHalf(casterRect.height()));
diff --git a/location/java/android/location/IFusedProvider.aidl b/location/java/android/location/IFusedProvider.aidl
index 8870d2a..e86ad1a 100644
--- a/location/java/android/location/IFusedProvider.aidl
+++ b/location/java/android/location/IFusedProvider.aidl
@@ -22,11 +22,11 @@
  * Interface definition for Location providers that require FLP services.
  * @hide
  */
-interface IFusedProvider {
+oneway interface IFusedProvider {
     /**
      * Provides access to a FusedLocationHardware instance needed for the provider to work.
      *
      * @param instance      The FusedLocationHardware available for the provider to use.
      */
     void onFusedLocationHardwareChange(in IFusedLocationHardware instance);
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/IGeofenceProvider.aidl b/location/java/android/location/IGeofenceProvider.aidl
index 5a5fdc6..d4ff0dd 100644
--- a/location/java/android/location/IGeofenceProvider.aidl
+++ b/location/java/android/location/IGeofenceProvider.aidl
@@ -23,6 +23,6 @@
  *
  * {@hide}
  */
-interface IGeofenceProvider {
+oneway interface IGeofenceProvider {
     void setGeofenceHardware(in IGeofenceHardware proxy);
 }
diff --git a/media/java/android/media/IRingtonePlayer.aidl b/media/java/android/media/IRingtonePlayer.aidl
index 4b1e39f..5f6686a 100644
--- a/media/java/android/media/IRingtonePlayer.aidl
+++ b/media/java/android/media/IRingtonePlayer.aidl
@@ -26,14 +26,14 @@
  */
 interface IRingtonePlayer {
     /** Used for Ringtone.java playback */
-    void play(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping);
-    void stop(IBinder token);
+    oneway void play(IBinder token, in Uri uri, in AudioAttributes aa, float volume, boolean looping);
+    oneway void stop(IBinder token);
     boolean isPlaying(IBinder token);
-    void setPlaybackProperties(IBinder token, float volume, boolean looping);
+    oneway void setPlaybackProperties(IBinder token, float volume, boolean looping);
 
     /** Used for Notification sound playback. */
-    void playAsync(in Uri uri, in UserHandle user, boolean looping, in AudioAttributes aa);
-    void stopAsync();
+    oneway void playAsync(in Uri uri, in UserHandle user, boolean looping, in AudioAttributes aa);
+    oneway void stopAsync();
 
     /** Return the title of the media. */
     String getTitle(in Uri uri);
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index c2ca998..f442219 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -26,16 +26,6 @@
         android:directBootAware="true">
 
         <library android:name="android.ext.services"/>
-
-        <service android:name=".notification.Ranker"
-                android:label="@string/notification_ranker"
-                android:permission="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
-                android:exported="true">
-            <intent-filter>
-                <action android:name="android.service.notification.NotificationRankerService" />
-            </intent-filter>
-        </service>
-
     </application>
 
 </manifest>
diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml
index b77ff10..531e517 100644
--- a/packages/ExtServices/res/values/strings.xml
+++ b/packages/ExtServices/res/values/strings.xml
@@ -16,6 +16,4 @@
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name">Android Services Library</string>
-    <string name="notification_ranker">Android Notification Ranking Service</string>
-    <string name="notification_ranker_autobundle_explanation">Auto-grouping updated by Ranking Service</string>
 </resources>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Ranker.java b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
deleted file mode 100644
index 2feb51f..0000000
--- a/packages/ExtServices/src/android/ext/services/notification/Ranker.java
+++ /dev/null
@@ -1,48 +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.ext.services.notification;
-
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.service.notification.Adjustment;
-import android.service.notification.NotificationRankerService;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-import android.util.Slog;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-
-import android.ext.services.R;
-
-/**
- * Class that provides an updatable ranker module for the notification manager.
- * TODO: delete
- */
-public final class Ranker extends NotificationRankerService {
-    private static final String TAG = "RocketRanker";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    @Override
-    public Adjustment onNotificationEnqueued(StatusBarNotification sbn, int importance,
-            boolean user) {
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 0474df7..d12417b 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -34,7 +34,7 @@
 import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.policy.EmergencyAffordanceManager;
diff --git a/packages/PrintSpooler/res/values-bs-rBA/strings.xml b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
index a50391f..2450be3 100644
--- a/packages/PrintSpooler/res/values-bs-rBA/strings.xml
+++ b/packages/PrintSpooler/res/values-bs-rBA/strings.xml
@@ -32,7 +32,7 @@
     <string name="template_page_range" msgid="428638530038286328">"Opseg od <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"npr. 1—5,8,11—13"</string>
     <string name="print_preview" msgid="8010217796057763343">"Pregled prije štampanja"</string>
-    <string name="install_for_print_preview" msgid="6366303997385509332">"Instaliraj PDF preglednik za prikaz"</string>
+    <string name="install_for_print_preview" msgid="6366303997385509332">"Instaliraj PDF pregledavač za prikaz"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"Aplikacija za štampanje je prestala raditi"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"Kreiranje zadatka za štampu"</string>
     <string name="save_as_pdf" msgid="5718454119847596853">"Sačuvaj kao PDF"</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
index 1bebebc..7b0a291 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
@@ -48,7 +48,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.printspooler.R;
 
 import java.text.Collator;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 23c6615..4b51917 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -88,7 +88,7 @@
 
 import android.widget.Toast;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.printspooler.R;
 import com.android.printspooler.model.MutexFileProvider;
 import com.android.printspooler.model.PrintSpoolerProvider;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 74582f3..6f0caa2 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -63,7 +63,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.printspooler.R;
 
 import java.util.ArrayList;
diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
index 381f903..c3acf0b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
@@ -35,7 +35,7 @@
 import android.view.MenuItem;
 import android.view.MenuItem.OnMenuItemClickListener;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.net.URISyntaxException;
 import java.util.Locale;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 227d0e9..d4c7c7a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -112,6 +112,7 @@
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
+    <uses-permission android:name="android.permission.MANAGE_AUTO_FILL" />
     <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
     <!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 772c344..dedb9ac 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -44,7 +44,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import com.google.android.collect.Lists;
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ea070b3..5294c9c 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Maak <xliff:g id="ID_1">%s</xliff:g>-instellings oop."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Wysig volgorde van instellings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Vou uit"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 837d677..601930a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"የ<xliff:g id="ID_1">%s</xliff:g> ቅንብሮችን ክፈት።"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"የቅንብሮድ ቅደም-ተከተል አርትዕ።"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ገጽ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ዘርጋ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f207dbc1..502a94e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -656,6 +656,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"فتح إعدادات <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"تعديل ترتيب الإعدادات."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"توسيع"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index c4b0f73..1bc9e59 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını açın."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ayarların sıralanmasını redaktə edin."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Genişləndirin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index e70e485..8105d9e 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvori podešavanja za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Izmeni redosled podešavanja."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index 7f7a67f..83c67d4 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -654,6 +654,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Адкрыць налады <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Змяніць парадак налад."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Разгарнуць"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 16dfeeb..bf3a614 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отваряне на настройките за <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Редактиране на подредбата на настройките."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Разгъване"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index f8ee362..bd599bc 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> সেটিংস খুলুন৷"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ক্রম বা সেটিংস সম্পাদনা করুন৷"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"প্রসারিত করুন"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 0e91713..5ba720c 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -652,6 +652,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvori postavke za: <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Urediti raspored postavki."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index d258943..927e75b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Obre la configuració per a <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edita l\'ordre de la configuració."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Desplega"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 845c8b5..69629a9 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -654,6 +654,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otevřít nastavení aplikace <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Upravit pořadí nastavení."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbalit"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index bb340a6..b0a828f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Åbn <xliff:g id="ID_1">%s</xliff:g>-indstillinger."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Rediger rækkefølgen af indstillinger."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Udvid"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index faabbfa..b3a457d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Einstellungen für <xliff:g id="ID_1">%s</xliff:g> öffnen."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Reihenfolge der Einstellungen bearbeiten."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Maximieren"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0f5f447..050d7f8 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Άνοιγμα ρυθμίσεων <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Επεξεργασία σειράς ρυθμίσεων."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Ανάπτυξη"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 14d2a19..9aca3cc 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 14d2a19..9aca3cc 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 14d2a19..9aca3cc 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Open <xliff:g id="ID_1">%s</xliff:g> settings."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit order of settings."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Expand"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 3b92a3a..90c2ca1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir configuración de <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar orden de configuración"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 600d7d5..0a45ac1 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir ajustes de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Cambiar el orden de los ajustes."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Mostrar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 884eac5..84fadb2 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ava teenuse <xliff:g id="ID_1">%s</xliff:g> seaded."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Muuda seadete järjestust."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Laiendamine"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index b5e6696..d6578a2 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ireki <xliff:g id="ID_1">%s</xliff:g> ezarpenak."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editatu ezarpenen ordena."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Zabaldu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 866904c..e00c5b5 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"باز کردن تنظیمات <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ویرایش ترتیب تنظیمات."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"بزرگ کردن"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 144704d..08572fe 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Avaa kohteen <xliff:g id="ID_1">%s</xliff:g> asetukset."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Muokkaa asetusten järjestystä."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Laajenna"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index b5c227e..830bfa7 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifier l\'ordre des paramètres."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 008d061..3b138c2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifier l\'ordre des paramètres."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Développer"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index cca60a8..579335d 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir a configuración de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar a orde das opcións de configuración."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Despregar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 558a90a..48a6d0f 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> સેટિંગ્સ ખોલો."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"સેટિંગ્સનો ક્રમ સંપાદિત કરો."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"વિસ્તૃત કરો"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1fff051..f482caaa 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग खोलें."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिंग का क्रम संपादित करें."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index ae7e0c4..7ff63bd 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvaranje postavki za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Uređivanje redoslijeda postavki."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Proširivanje"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index ec62e1c..bd0805b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"A(z) <xliff:g id="ID_1">%s</xliff:g> beállításainak megnyitása."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Beállítások sorrendjének szerkesztése."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Kibontás"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 80cb977..2f5358e 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Բացել <xliff:g id="ID_1">%s</xliff:g> կարգավորումները:"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Խմբագրել կարգավորումների հերթականությունը:"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Ընդարձակել"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 93960e8..6444ae5 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buka setelan <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit urutan setelan."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Luaskan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 71ef4bb..7e08a01 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Opna <xliff:g id="ID_1">%s</xliff:g> stillingar."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Breyta röð stillinga."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Stækka"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 12d0ed6..8ffb10d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Apri le impostazioni <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifica l\'ordine delle impostazioni."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Espandi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index f565603..a6d7983 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -652,6 +652,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"פתיחת הגדרות של <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"עריכת סדר ההגדרות."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"הרחב"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 37bea17..6ef9f73 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> の設定を開きます。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"設定の順序を編集します。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ページ <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 15f5d63..695279d 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> პარამეტრების გახსნა."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"პარამეტრების მიმდევრობის რედაქტირება."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"გაშლა"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 477ab82..ba71182 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> параметрлерін ашу."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Параметрлер тәртібін өзгерту."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Жаю"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 45771d9..b222555 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"បើការកំណត់ <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"កែលំដាប់ការកំណត់"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ពង្រីក"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 87c48dd..b2a6f27 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಕ್ರಮವನ್ನು ಎಡಿಟ್ ಮಾಡಿ."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ವಿಸ್ತೃತಗೊಳಿಸು"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3e0cdfe..cefb57a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> 설정 열기"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"설정 순서 수정"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"펼치기"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 2d8be38..e013c6b 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> жөндөөлөрүн ачуу."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Жөндөөлөрдүн иретин өзгөртүү."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Жайып көрсөтүү"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 93098ad..94e789a 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"ເປີດການຕັ້ງຄ່າ <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ແກ້ໄຂລຳດັບການຕັ້ງຄ່າ."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ຂະຫຍາຍ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 02e614c..5af5979 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -652,6 +652,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Atidaryti „<xliff:g id="ID_1">%s</xliff:g>“ nustatymus."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Redaguoti nustatymų tvarką."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Išskleisti"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 82f5f22..503c8c8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Atvērt <xliff:g id="ID_1">%s</xliff:g> iestatījumus."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Rediģēt iestatījumu secību."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Izvērst"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index fcaa26f..62fc350 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отворете ги поставките на <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Уредете го редоследот на поставките."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Проширете"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 44d76d5..9e7d2f2 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ക്രമീകരണം തുറക്കുക."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ക്രമീകരണ ക്രമം എഡിറ്റുചെയ്യുക."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"പേജ് <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"വികസിപ്പിക്കുക"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 1c7bc38..04fb4c2 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> тохиргоог нээнэ үү."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Тохиргооны дарааллыг өөрчилнө үү."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Дэлгэх"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 71d6677..a21019a 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग्ज उघडा."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिंग्जचा क्रम संपादित करा."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"पृष्ठ <xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत करा"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index bc9d79f..ce94295 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buka tetapan <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Edit susunan tetapan."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Kembangkan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 37c002c..8ab1de0 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ဆက်တင်များကို ဖွင့်ပါ။"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ဆက်တင်များ၏ အစီအစဉ်ကို တည်းဖြတ်ပါ။"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ချဲ့ရန်"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 025c270..c6312e1 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Åpne <xliff:g id="ID_1">%s</xliff:g>-innstillingene."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Endre rekkefølgen på innstillingene."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Vis"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 3ed5782..f87223c 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> सम्बन्धी सेटिङहरूलाई खोल्नुहोस्।"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"सेटिङहरूको क्रमलाई सम्पादन गर्नुहोस्।"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"विस्तृत गर्नुहोस्"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 13ef0f6..7c12b5fd 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g>-instellingen openen."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Volgorde van instellingen bewerken."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Uitvouwen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 553b604..f25662b 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ਸੈਟਿੰਗਾਂ ਦੇ ਕ੍ਰਮ ਦਾ ਸੰਪਾਦਨ ਕਰੋ।"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 5c7ea4f..d037cda 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Abrir as definições de <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editar a ordem das definições."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0d42645..e33ebb5 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -652,6 +652,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Deschideți setările <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Editați ordinea setărilor."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Extindeți"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9adc9fe..0fbb0bd 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -654,6 +654,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Открыть настройки <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Изменить порядок быстрых настроек."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Развернуть"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 6739ea1..c4d2378 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> සැකසීම් විවෘත කරන්න."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"සැකසීම්වල අනුපිළිවෙළ සංංස්කරණය කරන්න."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"දිග හරින්න"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 44881bd..23daf91 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -654,6 +654,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Otvoriť nastavenia <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Upraviť poradie nastavení"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbaliť"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index cc11704..90985e7 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -654,6 +654,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Odpri nastavitve za <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Uredi vrstni red nastavitev."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Razširi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 55598bd..9616c07 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Hap cilësimet e <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Modifiko rendin e cilësimeve."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Zgjero"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 22bd853..667c65d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Отвори подешавања за <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Измени редослед подешавања."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Прошири"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 87acdb3..0a95017 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Öppna <xliff:g id="ID_1">%s</xliff:g>-inställningarna."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ändra ordning på inställningarna."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sida <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Utöka"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index cc4391ce..afc5ee4 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Fungua mipangilio ya <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Badilisha orodha ya mipangilio."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Panua"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 2d3c27f..99b8439 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> அமைப்புகளைத் திற."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"அமைப்புகளின் வரிசை முறையைத் திருத்து."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"விரி"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 9fa3f86..c1aeb09 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> సెట్టింగ్‌లను తెరవండి."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"సెట్టింగ్‌ల క్రమాన్ని సవరించండి."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"విస్తరింపజేయి"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f59e69b..0c461b4 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"เปิดการตั้งค่า <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"แก้ไขลำดับการตั้งค่า"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"ขยาย"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2d978c4..caa9f97 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Buksan ang mga setting ng <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"I-edit ang pagkakasunud-sunod ng mga setting."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Palawakin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index e3827f7..030c97f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını aç."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Ayarların sırasını düzenle."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Genişlet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index fd627cc..c086fff 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -654,6 +654,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Відкрити налаштування <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Змінити порядок налаштувань."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Розгорнути"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 415c5b6..ff46ad3 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ترتیبات کھولیں۔"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ترتیبات کی ترتیب میں ترمیم کریں۔"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"پھیلائیں"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index aaea5e5..f2d2661 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> sozlamalarini ochish."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Sozlamalar tartibini o‘zgartirish."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Yoyish"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4ae3370..48b1e4f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Mở cài đặt <xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Chỉnh sửa thứ tự cài đặt."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Mở rộng"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7c7bc4a..94c3af1 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"打开<xliff:g id="ID_1">%s</xliff:g>设置。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"修改设置顺序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"展开"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e41a24b..5785af9 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -650,6 +650,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"開啟<xliff:g id="ID_1">%s</xliff:g>設定頁面。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"編輯設定次序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 51e27a3..6562b39 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"開啟「<xliff:g id="ID_1">%s</xliff:g>」設定。"</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"編輯設定順序。"</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 887da2e..e3c419b 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -648,6 +648,5 @@
     <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"Vula izilungiselelo ze-<xliff:g id="ID_1">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"Hlela uhlelo lwezilungiselelo."</string>
     <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string>
-    <!-- no translation found for pip_phone_expand (5889780005575693909) -->
-    <skip />
+    <string name="pip_phone_expand" msgid="5889780005575693909">"Nweba"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
index b1f454e..965ded5 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
@@ -35,8 +35,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
-import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
 
 /**
  * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
index b39803a..f8b73a1 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -22,10 +22,10 @@
 
 import java.util.ArrayList;
 
-import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.PhoneEvent;
-import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.SensorEvent;
-import static com.android.systemui.statusbar.phone.TouchAnalyticsProto.Session.TouchEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
 
 /**
  * Collects touch, sensor and phone events and converts the data to
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index b3038b9..870d4d1 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -78,10 +78,10 @@
         log("pulseFinish");
     }
 
-    public static void traceNotificationPulse(Context context, long instance) {
+    public static void traceNotificationPulse(Context context) {
         if (!ENABLED) return;
         init(context);
-        log("notificationPulse instance=" + instance);
+        log("notificationPulse");
         sNotificationPulseStats.append();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index bb4ea2d..9cc927d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -34,7 +34,7 @@
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 9df8113..9f26b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -87,6 +87,7 @@
         mNotificationPulseTime = SystemClock.elapsedRealtime();
         if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
         requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
+        DozeLog.traceNotificationPulse(mContext);
     }
 
     private void onWhisper() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 816d70d..fe9f55f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -136,7 +136,7 @@
 
         @Override // Binder interface
         public void onScreenTurnedOn() {
-            Trace.beginSection("KeyguardService.mBinder#onScreenTurningOn");
+            Trace.beginSection("KeyguardService.mBinder#onScreenTurnedOn");
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOn();
             Trace.endSection();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 9ae341a..8f1a943 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -285,6 +285,7 @@
     private LockPatternUtils mLockPatternUtils;
     private boolean mKeyguardDonePending = false;
     private boolean mHideAnimationRun = false;
+    private boolean mHideAnimationRunning = false;
 
     private SoundPool mLockSounds;
     private int mLockSoundId;
@@ -515,9 +516,7 @@
                 return;
             }
 
-            if (!mKeyguardDonePending) {
-                KeyguardViewMediator.this.handleKeyguardDone(true /* authenticated */);
-            }
+            tryKeyguardDone(true);
             if (strongAuth) {
                 mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
             }
@@ -545,7 +544,8 @@
 
             mKeyguardDonePending = true;
             mHideAnimationRun = true;
-            mStatusBarKeyguardViewManager.startPreHideAnimation(null /* finishRunnable */);
+            mHideAnimationRunning = true;
+            mStatusBarKeyguardViewManager.startPreHideAnimation(mHideAnimationFinishedRunnable);
             mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_PENDING_TIMEOUT,
                     KEYGUARD_DONE_PENDING_TIMEOUT_MS);
             if (strongAuth) {
@@ -565,9 +565,11 @@
         public void readyForKeyguardDone() {
             Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#readyForKeyguardDone");
             if (mKeyguardDonePending) {
+                mKeyguardDonePending = false;
+
                 // Somebody has called keyguardDonePending before, which means that we are
                 // authenticated
-                KeyguardViewMediator.this.handleKeyguardDone(true /* authenticated */);
+                tryKeyguardDone(true);
             }
             Trace.endSection();
         }
@@ -643,9 +645,7 @@
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
         setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled(
-                KeyguardUpdateMonitor.getCurrentUser()));
-        updateInputRestrictedLocked();
-        mTrustManager.reportKeyguardShowingChanged();
+                KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
 
         mStatusBarKeyguardViewManager =
                 SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
@@ -1257,7 +1257,7 @@
      */
     public void handleDismiss(boolean allowWhileOccluded) {
         if (mShowing && (allowWhileOccluded || !mOccluded)) {
-            mStatusBarKeyguardViewManager.dismiss();
+            mStatusBarKeyguardViewManager.dismissAndCollapse();
         }
     }
 
@@ -1493,6 +1493,16 @@
         }
     };
 
+    private void tryKeyguardDone(boolean authenticated) {
+        if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
+            handleKeyguardDone(authenticated);
+        } else if (!mHideAnimationRun) {
+            mHideAnimationRun = true;
+            mHideAnimationRunning = true;
+            mStatusBarKeyguardViewManager.startPreHideAnimation(mHideAnimationFinishedRunnable);
+        }
+    }
+
     /**
      * @see #keyguardDone
      * @see #KEYGUARD_DONE
@@ -1679,6 +1689,11 @@
         }
     };
 
+    private final Runnable mHideAnimationFinishedRunnable = () -> {
+        mHideAnimationRunning = false;
+        tryKeyguardDone(true);
+    };
+
     /**
      * Handle message sent by {@link #hideLocked()}
      * @see #HIDE
@@ -1697,16 +1712,10 @@
                 return;
             }
             mHiding = true;
-            if (mShowing && !mOccluded) {
-                if (!mHideAnimationRun) {
-                    mStatusBarKeyguardViewManager.startPreHideAnimation(mKeyguardGoingAwayRunnable);
-                } else {
-                    mKeyguardGoingAwayRunnable.run();
-                }
-            } else {
 
-                // Don't try to rely on WindowManager - if Keyguard wasn't showing, window
-                // manager won't start the exit animation.
+            if (mShowing && !mOccluded) {
+                mKeyguardGoingAwayRunnable.run();
+            } else {
                 handleStartKeyguardExitAnimation(
                         SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
                         mHideAnimation.getDuration());
@@ -1806,7 +1815,7 @@
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
             setShowingLocked(true);
-            mStatusBarKeyguardViewManager.verifyUnlock();
+            mStatusBarKeyguardViewManager.dismissAndCollapse();
         }
         Trace.endSection();
     }
@@ -1969,7 +1978,11 @@
     }
 
     private void setShowingLocked(boolean showing) {
-        if (showing != mShowing) {
+        setShowingLocked(showing, false /* forceCallbacks */);
+    }
+
+    private void setShowingLocked(boolean showing, boolean forceCallbacks) {
+        if (showing != mShowing || forceCallbacks) {
             mShowing = showing;
             int size = mKeyguardStateCallbacks.size();
             for (int i = size - 1; i >= 0; i--) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index c699e27..49307d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -28,7 +28,7 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSContainer;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 39ce324..6856575 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -29,7 +29,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile.State;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index cf2c16d..f663c75 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -35,7 +35,7 @@
 import android.widget.Toolbar.OnMenuItemClickListener;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSContainer;
 import com.android.systemui.qs.QSDetailClipper;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 8d7f6ee..f2c3e61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -40,7 +40,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSIconView;
 import com.android.systemui.qs.customize.TileAdapter.Holder;
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 dc68112..28530d7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -37,7 +37,7 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index a980a7f..e57cd58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -26,7 +26,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index d89fbfd3c..e5a555a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -35,7 +35,7 @@
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.TextView;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.BatteryInfo;
 import com.android.settingslib.graph.UsageView;
 import com.android.systemui.BatteryMeterDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 18bde27..53010af 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -29,7 +29,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 61bad77..4abd84a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -26,7 +26,7 @@
 import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSDetailItems;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 7de883e..2183565 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -26,7 +26,7 @@
 import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 5ae7a76..77f063d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -22,7 +22,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.SecureSetting;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index aabafe1..0ff81e5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -19,7 +19,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index ec4ab51..544ee91 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -33,7 +33,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SysUIToast;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 0aa723e..8fdce65 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -25,7 +25,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.FlashlightController;
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 016c4b7..b888fc8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -29,7 +29,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 2a2cc46..f968816 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -30,7 +30,7 @@
 import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.qs.QSTile;
 
 import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 5b5ecae..4b89075 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -23,7 +23,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index c02e5ae..10fde30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -23,7 +23,7 @@
 
 import com.android.internal.app.NightDisplayController;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 499eb50..eb4c510 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -24,7 +24,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.RotationLockController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index cd09231c..91d38bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -24,7 +24,7 @@
 import android.view.ViewGroup;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.PseudoGridView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index b5fbfe0..e79e519 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -21,7 +21,7 @@
 import android.provider.Settings;
 import android.util.Pair;
 
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.UserInfoController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 27306fc..9ce748f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -28,7 +28,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 459e8ec..ce7fbd3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -21,7 +21,7 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index e203c2f..7655e6c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -41,7 +41,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.EventLogConstants;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index ec99d20..af1823c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -40,7 +40,7 @@
 import android.view.WindowManager.LayoutParams;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Interpolators;
 import com.android.keyguard.LatencyTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
index 96644b5..9ed4924 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
@@ -15,12 +15,13 @@
  */
 package com.android.systemui.recents.grid;
 
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
 import android.app.Activity;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,7 +32,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
@@ -70,11 +71,12 @@
 
     private TaskStack mTaskStack;
     private List<Task> mTasks = new ArrayList<>();
-    private List<View> mTaskViews = new ArrayList<>();
+    private List<TaskView> mTaskViews = new ArrayList<>();
     private FrameLayout mRecentsView;
     private TextView mEmptyView;
     private View mClearAllButton;
-    private int mDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
+    private int mLastDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
+    private int mLastDisplayDensity;
     private Rect mDisplayRect = new Rect();
     private LayoutInflater mInflater;
     private boolean mTouchExplorationEnabled;
@@ -86,8 +88,10 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         mInflater = LayoutInflater.from(this);
-        mDisplayOrientation = Utilities.getAppConfiguration(this).orientation;
+        Configuration appConfiguration = Utilities.getAppConfiguration(this);
         mDisplayRect = ssp.getDisplayRect();
+        mLastDisplayOrientation = appConfiguration.orientation;
+        mLastDisplayDensity = appConfiguration.densityDpi;
         mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
 
         mRecentsView = (FrameLayout) findViewById(R.id.recents_view);
@@ -122,16 +126,29 @@
         return (TaskView) mInflater.inflate(R.layout.recents_task_view, mRecentsView, false);
     }
 
-    private void clearTaskViews() {
+    private void removeTaskViews() {
         for (View taskView : mTaskViews) {
             ViewGroup parent = (ViewGroup) taskView.getParent();
             if (parent != null) {
                 parent.removeView(taskView);
             }
         }
+    }
+
+    private void clearTaskViews() {
+        removeTaskViews();
         mTaskViews.clear();
     }
 
+    private TaskView getChildViewForTask(Task task) {
+        for (TaskView tv : mTaskViews) {
+            if (tv.getTask() == task) {
+                return tv;
+            }
+        }
+        return null;
+    }
+
     private void updateControlVisibility() {
         boolean empty = (mTasks.size() == 0);
         mClearAllButton.setVisibility(empty ? View.INVISIBLE : View.VISIBLE);
@@ -170,7 +187,8 @@
         for (int i = 0; i < mTasks.size(); i++) {
             Task task = mTasks.get(i);
             TaskView taskView = createView();
-            taskView.onTaskBound(task, mTouchExplorationEnabled, mDisplayOrientation, mDisplayRect);
+            taskView.onTaskBound(task, mTouchExplorationEnabled, mLastDisplayOrientation,
+                    mDisplayRect);
             Recents.getTaskLoader().loadTaskData(task);
             taskView.setTouchEnabled(true);
             // Show dismiss button right away.
@@ -211,6 +229,22 @@
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        // Notify of the config change.
+        Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
+        mDisplayRect = Recents.getSystemServices().getDisplayRect();
+        mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
+        mRecentsView.requestLayout();
+        int numStackTasks = mTaskStack.getStackTaskCount();
+        EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
+                mLastDisplayOrientation != newDeviceConfiguration.orientation,
+                mLastDisplayDensity != newDeviceConfiguration.densityDpi, numStackTasks > 0));
+        mLastDisplayOrientation = newDeviceConfiguration.orientation;
+        mLastDisplayDensity = newDeviceConfiguration.densityDpi;
+    }
+
+    @Override
     public boolean onPreDraw() {
         mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
         int width = mRecentsView.getWidth();
@@ -218,6 +252,7 @@
 
         List<Rect> rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
             mTasks.size(), width, height, false /* allowLineOfThree */, 30 /* padding */);
+        removeTaskViews();
         for (int i = 0; i < rects.size(); i++) {
             Rect rect = rects.get(i);
             View taskView = mTaskViews.get(i);
@@ -235,20 +270,43 @@
         startActivity(startMain);
     }
 
+    /** Launches the task that recents was launched from if possible. */
+    boolean launchPreviousTask() {
+        if (mRecentsView != null) {
+            Task task = mTaskStack.getLaunchTarget();
+            if (task != null) {
+                TaskView taskView = getChildViewForTask(task);
+                EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
+                        INVALID_STACK_ID, false));
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Dismisses recents back to the launch target task. */
+    boolean dismissRecentsToLaunchTargetTaskOrHome() {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.isRecentsActivityVisible()) {
+            // If we can launch the task that Recents was launched from, do that, otherwise go home.
+            if (launchPreviousTask()) return true;
+            dismissRecentsToHome();
+        }
+        return false;
+    }
+
     /**** EventBus events ****/
 
     public final void onBusEvent(HideRecentsEvent event) {
         if (event.triggeredFromAltTab) {
-            // Do nothing for now.
+            dismissRecentsToLaunchTargetTaskOrHome();
         } else if (event.triggeredFromHomeKey) {
             dismissRecentsToHome();
         }
     }
 
     public final void onBusEvent(ToggleRecentsEvent event) {
-        // Always go back home for simplicity for now. If recents is entered from another app, this
-        // code will eventually need to go back to the original app.
-        dismissRecentsToHome();
+        dismissRecentsToLaunchTargetTaskOrHome();
     }
 
     public final void onBusEvent(DismissTaskViewEvent event) {
@@ -306,7 +364,22 @@
     }
 
     public final void onBusEvent(LaunchNextTaskRequestEvent event) {
-        // Always go back home for simplicity for now. Quick switch will be supported soon.
+        if (mTaskStack.getTaskCount() > 0) {
+            // The task to launch is the second most recent, which is at index 1 given our ordering.
+            // If there is only one task, launch that one instead.
+            int launchTaskIndex = (mTaskStack.getStackTaskCount() > 1) ? 1 : 0;
+            Task launchTask = mTaskStack.getStackTasks().get(launchTaskIndex);
+            TaskView launchTaskView = getChildViewForTask(launchTask);
+            if (launchTaskView != null) {
+                EventBus.getDefault().send(new LaunchTaskEvent(launchTaskView,
+                        launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+                MetricsLogger.action(this, MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+                        launchTask.key.getComponent().toString());
+                return;
+            }
+        }
+        // We couldn't find a matching task view, or there are no tasks. Just hide recents back
+        // to home.
         EventBus.getDefault().send(new HideRecentsEvent(false, true));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index febeacb..3c7012a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -43,7 +43,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
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 936354e..77c61f8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -47,7 +47,7 @@
 import android.widget.ScrollView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index d44aa84..71f559b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -34,7 +34,7 @@
 import android.view.animation.Interpolator;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e91c9d5..de7def6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -39,7 +39,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 3ed2698..e8039c3 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -33,7 +33,7 @@
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 803fe48..901d47d 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -25,7 +25,7 @@
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 
 /** A dialog that provides controls for adjusting the screen brightness. */
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 15d26f9..2684722 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -35,7 +35,7 @@
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.settingslib.accessibility.AccessibilityUtils;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 4e34bbc..47d2def 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -54,7 +54,7 @@
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 23acb1b..93ddd17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -87,7 +87,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.widget.LockPatternUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index caf5447..5173176 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -43,7 +43,7 @@
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index f438762..f43fc40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -59,7 +59,7 @@
 
 import com.android.internal.app.AssistUtils;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index b10fb31..bb327ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -43,7 +43,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.Utils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 0f800bb..228e8ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -27,7 +27,7 @@
 import android.view.ViewConfiguration;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c33d91a..2f3631c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -118,7 +118,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -1649,9 +1649,9 @@
             newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
 
             StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(),
-                    sbn.getOpPkg(),
+                    sbn.getOpPkg(), sbn.getNotificationChannel(),
                     sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
-                    0, newNotification, sbn.getUser(), sbn.getPostTime());
+                    newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
 
             updateNotification(newSbn, null);
             mKeysKeptForRemoteInput.add(entry.key);
@@ -3552,8 +3552,14 @@
                 AsyncTask.execute(runnable);
             }
             if (dismissShade) {
-                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
-                        true /* delayed*/);
+                if (mExpandedVisible) {
+                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
+                            true /* delayed*/);
+                } else {
+
+                    // Do it after DismissAction has been processed to conserve the needed ordering.
+                    mHandler.post(this::runPostCollapseRunnables);
+                }
             }
             return deferred;
         }, cancelAction, afterKeyguardGone);
@@ -3631,12 +3637,10 @@
         dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
     }
 
-    public void dismissKeyguard() {
-        mStatusBarKeyguardViewManager.dismiss();
-    }
-
     private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
             boolean afterKeyguardGone) {
+        afterKeyguardGone |= mStatusBarKeyguardViewManager.isShowing()
+                && mStatusBarKeyguardViewManager.isOccluded();
         if (mStatusBarKeyguardViewManager.isShowing()) {
             mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
                     afterKeyguardGone);
@@ -4249,7 +4253,7 @@
                     }
                 }, delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
             }
-        } else {
+        } else if (!mNotificationPanel.isCollapsing()) {
             instantCollapseNotificationPanel();
         }
         updateKeyguardState(staying, false /* fromShadeLocked */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index a8b0122..65c6347 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -33,7 +33,7 @@
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f5c5e56..69decd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -155,8 +155,8 @@
             if (!afterKeyguardGone) {
                 mBouncer.showWithDismissAction(r, cancelAction);
             } else {
-                mBouncer.show(false /* resetSecuritySelection */);
                 mAfterKeyguardGoneAction = r;
+                mBouncer.show(false /* resetSecuritySelection */);
             }
         }
         updateStates();
@@ -235,10 +235,6 @@
         mDeviceWillWakeUp = !mDeviceInteractive;
     }
 
-    public void verifyUnlock() {
-        dismiss();
-    }
-
     public void setNeedsInput(boolean needsInput) {
         mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
     }
@@ -333,6 +329,7 @@
                 }
             });
         } else {
+            executeAfterKeyguardGoneAction();
             if (mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING) {
                 mFingerprintUnlockController.startKeyguardFadingAway();
                 mPhoneStatusBar.setKeyguardFadingAway(startTime, 0, 240);
@@ -372,7 +369,6 @@
             mStatusBarWindowManager.setKeyguardShowing(false);
             mBouncer.hide(true /* destroyView */);
             mViewMediatorCallback.keyguardGone();
-            executeAfterKeyguardGoneAction();
             updateStates();
         }
     }
@@ -423,6 +419,10 @@
     /**
      * Dismisses the keyguard by going to the next screen or making it gone.
      */
+    public void dismissAndCollapse() {
+        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true);
+    }
+
     public void dismiss() {
         showBouncer();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 7b1f707..44ec283 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -50,7 +50,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 30d1c54..eda46c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -48,7 +48,7 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.GuestResumeSessionReceiver;
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 da58d9e..72a0e59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -57,7 +57,7 @@
 import android.widget.ScrollView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index 6e08139..9998283 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -21,7 +21,7 @@
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 
 import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index 0a3197c..0a962f1 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -31,7 +31,7 @@
 import android.view.MenuItem;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
index 14fccf2..8740a3c 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
@@ -16,7 +16,7 @@
 package com.android.systemui.tuner;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 
 import android.annotation.Nullable;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index f2f0382..dea2f50 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -24,7 +24,7 @@
 import android.util.AttributeSet;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.tuner.TunerService.Tunable;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 7f63418..f835e7d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -27,7 +27,7 @@
 import android.view.MenuItem;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginPrefs;
 
@@ -102,7 +102,9 @@
                 TunerService.showResetRequest(getContext(), new Runnable() {
                     @Override
                     public void run() {
-                        getActivity().finish();
+                        if (getActivity() != null) {
+                            getActivity().finish();
+                        }
                     }
                 });
                 return true;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index 8e0f9b8..ca53bc4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -23,7 +23,7 @@
 import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.volume.VolumeDialogController.State;
 
 import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 22d1309..87f6138 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -52,7 +52,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.ZenModeController;
diff --git a/services/Android.mk b/services/Android.mk
index 3385bed..2911983 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -22,6 +22,7 @@
     core \
     accessibility \
     appwidget \
+    autofill \
     backup \
     devicepolicy \
     midi \
diff --git a/services/autofill/Android.mk b/services/autofill/Android.mk
new file mode 100644
index 0000000..a1f19fd
--- /dev/null
+++ b/services/autofill/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.autofill
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
new file mode 100644
index 0000000..3b41877
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import static android.Manifest.permission.MANAGE_AUTO_FILL;
+import static android.content.Context.AUTO_FILL_MANAGER_SERVICE;
+
+import android.Manifest;
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.autofill.IAutoFillManagerService;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.FgThread;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Entry point service for auto-fill management.
+ *
+ * <p>This service provides the {@link IAutoFillManagerService} implementation and keeps a list of
+ * {@link AutoFillManagerServiceImpl} per user; the real work is done by
+ * {@link AutoFillManagerServiceImpl} itself.
+ */
+public final class AutoFillManagerService extends SystemService {
+
+    private static final String TAG = "AutoFillManagerService";
+    private static final boolean DEBUG = true; // TODO: change to false once stable
+
+    private final AutoFillManagerServiceStub mServiceStub;
+    private final Context mContext;
+    private final ContentResolver mResolver;
+
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private boolean mSafeMode;
+
+    /**
+     * Map of {@link AutoFillManagerServiceImpl} per user id.
+     * <p>
+     * It has to be mapped by user id because the same current user could have simultaneous sessions
+     * associated to different user profiles (for example, in a multi-window environment).
+     * <p>
+     * This map is filled on demand in the following scenarios:
+     * <ol>
+     *   <li>On start, it sets the value for the default user.
+     *   <li>When an auto-fill service app is removed, its entries are removed.
+     *   <li>When the current user changes.
+     *   <li>When the {@link android.provider.Settings.Secure#AUTO_FILL_SERVICE} changes.
+     * </ol>
+     */
+    // TODO: make sure all cases listed above are handled
+    // TODO: should entries be removed when there is no section and have not be used for a while?
+    @GuardedBy("mLock")
+    private SparseArray<AutoFillManagerServiceImpl> mImplByUser = new SparseArray<>();
+
+    // TODO: should disable it on low-memory devices? if not, this attribute should be removed...
+    private final boolean mEnableService = true;
+
+    public AutoFillManagerService(Context context) {
+        super(context);
+
+        mContext = context;
+        mResolver = context.getContentResolver();
+        mServiceStub = new AutoFillManagerServiceStub();
+    }
+
+    @Override
+    public void onStart() {
+        if (DEBUG)
+            Slog.d(TAG, "onStart(): binding as " + AUTO_FILL_MANAGER_SERVICE);
+        publishBinderService(AUTO_FILL_MANAGER_SERVICE, mServiceStub);
+    }
+
+    // TODO: refactor so it's bound on demand, in which case it can use isSafeMode() from PM.
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            systemRunning(isSafeMode());
+        }
+    }
+
+    // TODO: refactor so it's bound on demand, in which case it can use isSafeMode() from PM.
+    @Override
+    public void onStartUser(int userHandle) {
+        if (DEBUG) Slog.d(TAG, "onStartUser(): userHandle=" + userHandle);
+
+        updateImplementationIfNeeded(userHandle, false);
+    }
+
+    @Override
+    public void onUnlockUser(int userHandle) {
+        if (DEBUG) Slog.d(TAG, "onUnlockUser(): userHandle=" + userHandle);
+
+        updateImplementationIfNeeded(userHandle, false);
+    }
+
+    @Override
+    public void onSwitchUser(int userHandle) {
+        if (DEBUG) Slog.d(TAG, "onSwitchUser(): userHandle=" + userHandle);
+
+        updateImplementationIfNeeded(userHandle, false);
+    }
+
+    private void systemRunning(boolean safeMode) {
+        if (DEBUG) Slog.d(TAG, "systemRunning(): safeMode=" + safeMode);
+
+        // TODO: register a PackageMonitor
+        new SettingsObserver(BackgroundThread.getHandler());
+
+        synchronized (mLock) {
+            mSafeMode = safeMode;
+            updateImplementationIfNeededLocked(ActivityManager.getCurrentUser(), false);
+        }
+    }
+
+    private void updateImplementationIfNeeded(int user, boolean force) {
+        synchronized (mLock) {
+            updateImplementationIfNeededLocked(user, force);
+        }
+    }
+
+    private void updateImplementationIfNeededLocked(int user, boolean force) {
+        if (DEBUG)
+            Slog.d(TAG, "updateImplementationIfNeededLocked(" + user + ", " + force + ")");
+
+        if (mSafeMode) {
+            if (DEBUG) Slog.d(TAG, "skipping on safe mode");
+            return;
+        }
+
+        final String curService = Settings.Secure.getStringForUser(
+                mResolver, Settings.Secure.AUTO_FILL_SERVICE, user);
+        if (DEBUG)
+            Slog.d(TAG, "Current service settings for user " + user + ": " + curService);
+        ComponentName serviceComponent = null;
+        ServiceInfo serviceInfo = null;
+        if (!TextUtils.isEmpty(curService)) {
+            try {
+                serviceComponent = ComponentName.unflattenFromString(curService);
+                serviceInfo =
+                        AppGlobals.getPackageManager().getServiceInfo(serviceComponent, 0, user);
+            } catch (RuntimeException | RemoteException e) {
+                Slog.wtf(TAG, "Bad auto-fill service name " + curService, e);
+                serviceComponent = null;
+                serviceInfo = null;
+            }
+        }
+
+        final AutoFillManagerServiceImpl impl = mImplByUser.get(user);
+        if (DEBUG) Slog.d(TAG, "Current impl: " + impl + " component: " + serviceComponent
+                + " info: " + serviceInfo);
+
+        if (force || impl == null || !impl.mComponent.equals(serviceComponent)) {
+            if (impl != null) {
+                impl.shutdownLocked();
+            }
+            if (serviceInfo != null) {
+                final AutoFillManagerServiceImpl newImpl = new AutoFillManagerServiceImpl(mContext,
+                        mLock, mServiceStub, FgThread.getHandler(), user, serviceComponent);
+                if (DEBUG) Slog.d(TAG, "Setting impl for user " + user + " as: " + newImpl);
+                mImplByUser.put(user, newImpl);
+                newImpl.startLocked();
+            } else {
+                if (DEBUG) Slog.d(TAG, "Removing impl for user " + user + ": " + impl);
+                mImplByUser.remove(user);
+            }
+        }
+    }
+
+    // TODO: might need to return null instead of throw exception
+    private AutoFillManagerServiceImpl getImplOrThrowLocked(int userId) {
+        final AutoFillManagerServiceImpl impl = mImplByUser.get(userId);
+        if (impl == null) {
+            throw new IllegalStateException("no auto-fill service for user " + userId);
+        }
+        return impl;
+    }
+
+    final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
+
+        @Override
+        public String startSession(int userId, Bundle args, int flags, IBinder activityToken) {
+            mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+            synchronized (mLock) {
+                return getImplOrThrowLocked(userId).startSession(args, flags, activityToken);
+            }
+        }
+
+        @Override
+        public boolean finishSession(int userId, String token) {
+            mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+            synchronized (mLock) {
+                return getImplOrThrowLocked(userId).finishSessionLocked(token);
+            }
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (mContext.checkCallingPermission(
+                    Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump autofill from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid());
+                return;
+            }
+            if (args.length > 0) {
+                if ("--sessions".equals(args[0])) {
+                    dumpSessions(pw);
+                    return;
+                }
+            }
+            synchronized (mLock) {
+                pw.print("mEnableService: "); pw.println(mEnableService);
+                pw.print("mSafeMode: "); pw.println(mSafeMode);
+                final int size = mImplByUser.size();
+                pw.print("Number of implementations: ");
+                if (size == 0) {
+                    pw.println("none");
+                } else {
+                    pw.println(size);
+                    for (int i = 0; i < size; i++) {
+                        pw.print("\nImplementation at index "); pw.println(i);
+                        final AutoFillManagerServiceImpl impl = mImplByUser.valueAt(i);
+                        impl.dumpLocked("  ", pw);
+                    }
+                }
+            }
+        }
+
+        private void dumpSessions(PrintWriter pw) {
+            boolean foundOne = false;
+            synchronized (mLock) {
+                final int size = mImplByUser.size();
+                for (int i = 0; i < size; i++) {
+                    final AutoFillManagerServiceImpl impl = mImplByUser.valueAt(i);
+                    foundOne |= impl.dumpSessionsLocked("", pw);
+                }
+            }
+            if (!foundOne) {
+                pw.println("No active sessions");
+            }
+        }
+
+        @Override
+        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+            (new AutoFillManagerServiceShellCommand(this)).exec(
+                    this, in, out, err, args, callback, resultReceiver);
+        }
+
+    }
+
+    private final class SettingsObserver extends ContentObserver {
+        SettingsObserver(Handler handler) {
+            super(handler);
+            ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.AUTO_FILL_SERVICE), false, this,
+                    UserHandle.USER_ALL);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            synchronized (mLock) {
+                updateImplementationIfNeededLocked(userId, false);
+            }
+        }
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
new file mode 100644
index 0000000..c780062
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.app.ActivityManagerInternal;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.autofill.AutoFillService;
+import android.service.autofill.AutoFillServiceInfo;
+import android.service.autofill.IAutoFillService;
+import android.util.Log;
+import android.util.PrintWriterPrinter;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
+import com.android.server.autofill.AutoFillManagerService.AutoFillManagerServiceStub;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Bridge between the {@code system_server}'s {@link AutoFillManagerService} and the
+ * app's {@link IAutoFillService} implementation.
+ *
+ * <p>It keeps a list of auto-fill sessions for a specifc user.
+ */
+final class AutoFillManagerServiceImpl {
+
+    private static final String TAG = "AutoFillManagerServiceImpl";
+    private static final boolean DEBUG = true; // TODO: change to false once stable
+
+    final int mUser;
+    final ComponentName mComponent;
+
+    private final Context mContext;
+    private final Object mLock;
+    private final AutoFillManagerServiceStub mServiceStub;
+    private final AutoFillServiceInfo mInfo;
+
+    // Map of sessions keyed by session tokens.
+    @GuardedBy("mLock")
+    private Map<String, AutoFillSession> mSessions = new HashMap<>();
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+                final String reason = intent.getStringExtra("reason");
+                if (DEBUG) Slog.d(TAG, "close system dialogs: " + reason);
+                // TODO: close any pending UI like account selection
+            }
+        }
+    };
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DEBUG) Log.d(TAG, "onServiceConnected():" + name);
+            synchronized (mLock) {
+                mService = IAutoFillService.Stub.asInterface(service);
+                try {
+                    mService.ready();
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Exception on service.ready(): " + e);
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DEBUG) Log.d(TAG, name + " disconnected");
+            mService = null;
+        }
+    };
+
+    @GuardedBy("mLock")
+    private IAutoFillService mService;
+    private boolean mBound;
+    private boolean mValid;
+
+    AutoFillManagerServiceImpl(Context context, Object lock, AutoFillManagerServiceStub stub,
+            Handler handler, int user, ComponentName component) {
+        mContext = context;
+        mLock = lock;
+        mServiceStub = stub;
+        mUser = user;
+        mComponent = component;
+
+        AutoFillServiceInfo info;
+        try {
+            info = new AutoFillServiceInfo(component, mUser);
+        } 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, handler);
+    }
+
+    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(mUser));
+        if (!mBound) {
+            Slog.w(TAG, "Failed binding to auto-fill service " + mComponent);
+            return;
+        }
+        if (DEBUG) Slog.d(TAG, "Bound to " + mComponent);
+    }
+
+    String startSession(Bundle args, int flags, IBinder activityToken) {
+
+        if (!mBound) {
+            // TODO: should it bind on demand? Or perhaps always run when on on low-memory?
+            Slog.w(TAG, "startSession() failed because it's not bound to service");
+            return null;
+        }
+
+        // TODO: session should have activity ids, so same session is reused when called again
+        // for the same activity.
+
+        // TODO: activityToken should probably not be null, but we need to wait until the UI is
+        // triggering the call (for now it's trough 'adb shell cmd autofill start session'
+        if (activityToken == null) {
+            // Let's get top activities from all visible stacks.
+
+            // TODO: overload getTopVisibleActivities() to take userId, otherwise it could return
+            // activities for different users when a work profile app is displayed in another
+            // window (in a multi-window environment).
+            final List<IBinder> topActivities = LocalServices
+                    .getService(ActivityManagerInternal.class).getTopVisibleActivities();
+            if (DEBUG)
+                Slog.d(TAG, "Top activities (" + topActivities.size() + "): " + topActivities);
+            if (topActivities.isEmpty()) {
+                Slog.w(TAG, "Could not get top activity");
+                return null;
+            }
+            activityToken = topActivities.get(0);
+        }
+
+        synchronized (mLock) {
+            return startSessionLocked(args, flags, activityToken);
+        }
+    }
+
+    // TODO: remove args and flags if not needed?
+    private String startSessionLocked(Bundle args, int flags, IBinder activityToken) {
+
+        final String sessionToken = UUID.randomUUID().toString();
+
+        if (DEBUG) Slog.d(TAG, "Starting session for user " + mUser
+                + ": sessionToken=" + sessionToken + ", activityToken=" + activityToken);
+
+        final AutoFillSession session =
+                new AutoFillSession(mService, mLock, sessionToken, activityToken);
+        session.startLocked();
+        mSessions.put(sessionToken, session);
+
+        return sessionToken;
+    }
+
+    // TODO: need a way to automatically call it when the activity is destroyed.
+    boolean finishSessionLocked(String token) {
+        if (DEBUG) Slog.d(TAG, "Removing session " + token + " for user " + mUser);
+        final AutoFillSession session = mSessions.remove(token);
+        if (session != null) {
+            session.finishLocked();
+        }
+        return session != null;
+    }
+
+    void shutdownLocked() {
+        if (DEBUG) Slog.d(TAG, "shutdownLocked()");
+
+        try {
+            if (mService != null) {
+                mService.shutdown();
+            }
+        } catch (RemoteException e) {
+            Slog.w(TAG, "RemoteException in shutdown", e);
+        }
+
+        if (mBound) {
+            mContext.unbindService(mConnection);
+            mBound = false;
+        }
+        if (mValid) {
+            mContext.unregisterReceiver(mBroadcastReceiver);
+        }
+    }
+
+    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;
+        }
+
+        pw.print(prefix); pw.print("mUser="); pw.println(mUser);
+        pw.print(prefix); pw.print("mComponent="); pw.println(mComponent.flattenToShortString());
+        pw.print(prefix); pw.print("mBound="); pw.println(mBound);
+        pw.print(prefix); pw.print("mService="); pw.println(mService);
+
+        if (DEBUG) {
+            // ServiceInfo dump is too noisy and redundant (it can be obtained through other dumps)
+            pw.print(prefix); pw.println("Service info:");
+            mInfo.getServiceInfo().dump(new PrintWriterPrinter(pw), prefix + prefix);
+        }
+
+        if (!dumpSessionsLocked(prefix, pw)) {
+            pw.print(prefix); pw.print("No active sessions for user "); pw.println(mUser);
+        }
+    }
+
+    boolean dumpSessionsLocked(String prefix, PrintWriter pw) {
+        if (mSessions.isEmpty()) {
+            return false;
+        }
+
+        pw.print(mSessions.size());pw.println(" active sessions:");
+        final String sessionPrefix = prefix + prefix;
+        for (AutoFillSession session : mSessions.values()) {
+            pw.println();
+            session.dumpLocked(sessionPrefix, pw);
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "[AutoFillManagerServiceImpl: user=" + mUser
+                + ", component=" + mComponent.flattenToShortString() + "]";
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
new file mode 100644
index 0000000..4e08ed6
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.app.ActivityManager;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.service.autofill.IAutoFillManagerService;
+
+import java.io.PrintWriter;
+
+public final class AutoFillManagerServiceShellCommand extends ShellCommand {
+
+    private final IAutoFillManagerService.Stub mService;
+
+    public AutoFillManagerServiceShellCommand(IAutoFillManagerService.Stub service) {
+        mService = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            switch (cmd) {
+                case "start":
+                    return runStart(pw);
+                case "finish":
+                    return runFinish(pw);
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (RemoteException e) {
+            pw.println("error: " + e);
+        }
+        return -1;
+    }
+
+    @Override
+    public void onHelp() {
+        try (final PrintWriter pw = getOutPrintWriter();) {
+            pw.println("AutoFill Service (autofill) commands:");
+            pw.println("  help");
+            pw.println("    Prints this help text.");
+            pw.println("");
+            pw.println("  start session [--user USER_ID]");
+            pw.println("    Starts an auto-fill session. "
+                    + "Prints 'token:SESSION_TOKEN if successful, or error message");
+            pw.println("");
+            pw.println("  finish session <TOKEN> [--user USER_ID]");
+            pw.println("    Finishes a session with the given TOKEN. "
+                    + "Prints empty string if successful, or error message.");
+            pw.println("");
+        }
+    }
+
+    private int runStart(PrintWriter pw) throws RemoteException {
+        final String type = getNextArg();
+        if (type == null) {
+            pw.println("Error: didn't specify type of data to start");
+            return -1;
+        }
+        switch (type) {
+            case "session":
+                return startAutoFillSession(pw);
+        }
+        pw.println("Error: unknown start type '" + type + "'");
+        return -1;
+    }
+
+    private int runFinish(PrintWriter pw) throws RemoteException {
+        final String type = getNextArg();
+        if (type == null) {
+            pw.println("Error: didn't specify type of data to finish");
+            return -1;
+        }
+        switch (type) {
+            case "session":
+                return finishAutoFillSession(pw);
+        }
+        pw.println("Error: unknown finish type '" + type + "'");
+        return -1;
+    }
+
+    private int startAutoFillSession(PrintWriter pw) throws RemoteException {
+        final int userId = getUserIdFromArgs();
+        final String token = mService.startSession(userId, null, 0, null);
+        pw.print("token:"); pw.println(token);
+        return 0;
+    }
+
+    private int finishAutoFillSession(PrintWriter pw) throws RemoteException {
+        final String token = getNextArgRequired();
+        final int userId = getUserIdFromArgs();
+
+        boolean finished = mService.finishSession(userId, token);
+        if (!finished) {
+            pw.println("No such session");
+            return 1;
+        }
+        return 0;
+    }
+
+    private int getUserIdFromArgs() {
+        if ("--user".equals(getNextArg())) {
+            return UserHandle.parseUserArg(getNextArgRequired());
+        }
+        return ActivityManager.getCurrentUser();
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillSession.java b/services/autofill/java/com/android/server/autofill/AutoFillSession.java
new file mode 100644
index 0000000..44637c3
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AutoFillSession.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.autofill;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.autofill.AutoFillService;
+import android.service.autofill.IAutoFillService;
+import android.service.voice.VoiceInteractionSession;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.IResultReceiver;
+
+import java.io.PrintWriter;
+
+/**
+ * An auto-fill session between the system's {@link AutoFillManagerServiceImpl} and the provider's
+ * {@link AutoFillService} implementation.
+ */
+final class AutoFillSession {
+
+    private static final String TAG = "AutoFillSession";
+
+    private static final boolean FOCUSED = true;
+    private static final boolean NEW_SESSION_ID = true;
+
+    private final IAutoFillService mService;
+    private final String mSessionToken;
+    private final IBinder mActivityToken;
+    private final Object mLock;
+    private final IActivityManager mAm;
+
+    private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
+        @Override
+        public void send(int resultCode, Bundle resultData) throws RemoteException {
+            synchronized (mLock) {
+                mPendingResponse = false;
+                mAssistResponse = resultData;
+                deliverSessionDataLocked();
+            }
+        }
+    };
+
+    // Assist data is filled asynchronously.
+    @GuardedBy("mLock")
+    private Bundle mAssistResponse;
+    @GuardedBy("mLock")
+    private boolean mPendingResponse;
+
+    AutoFillSession(IAutoFillService service, Object lock, String sessionToken,
+            IBinder activityToken) {
+        mService = service;
+        mSessionToken = sessionToken;
+        mActivityToken = activityToken;
+        mLock = lock;
+        mAm = ActivityManagerNative.getDefault();
+    }
+
+    void startLocked() {
+        /*
+         * TODO: apply security checks below:
+         * - checks if disabled by secure settings / device policy
+         * - log operation using noteOp()
+         * - check flags
+         * - display disclosure if needed
+         */
+        mAssistResponse = null;
+        mPendingResponse = true;
+        try {
+            // TODO: add MetricsLogger call
+            if (!mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
+                    mAssistReceiver, (Bundle) null, mActivityToken, FOCUSED, NEW_SESSION_ID)) {
+                mPendingResponse = false;
+                Slog.w(TAG, "requestAssistContextExtras() rejected");
+            }
+        } catch (RemoteException e) {
+            // Should happen, it's a local call.
+        }
+    }
+
+    void finishLocked() {
+        try {
+            mService.finishSession(mSessionToken);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "auto-fill service failed to finish session " + mSessionToken, e);
+        }
+    }
+
+    private void deliverSessionDataLocked() {
+        if (mAssistResponse == null) {
+            Slog.w(TAG, "No assist data for session " + mSessionToken);
+            return;
+        }
+
+        final Bundle assistData = mAssistResponse.getBundle(VoiceInteractionSession.KEY_DATA);
+        final AssistStructure structure =
+                mAssistResponse.getParcelable(VoiceInteractionSession.KEY_STRUCTURE);
+        try {
+            mService.newSession(mSessionToken, assistData, 0, structure);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "auto-fill service failed to start session " + mSessionToken, e);
+        } finally {
+            mPendingResponse = false;
+            // We could set mAssistResponse to null here, but we don't so it's shown on dump()
+        }
+    }
+
+    void dumpLocked(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("mSessionToken="); pw.println(mSessionToken);
+        pw.print(prefix); pw.print("mActivityToken="); pw.println(mActivityToken);
+        pw.print(prefix); pw.print("mPendingResponse="); pw.println(mPendingResponse);
+        pw.print(prefix); pw.print("mAssistResponse="); pw.println(mAssistResponse);
+    }
+
+}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 82897fb..2558045 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1940,13 +1940,9 @@
         }
         for (int i = mPendingWhileIdleAlarms.size() - 1; i >= 0; i--) {
             final Alarm a = mPendingWhileIdleAlarms.get(i);
-            try {
-                if (a.uid == uid && ActivityManagerNative.getDefault().getAppStartMode(
-                        uid, a.packageName) == ActivityManager.APP_START_MODE_DISABLED) {
-                    // Don't set didRemove, since this doesn't impact the scheduled alarms.
-                    mPendingWhileIdleAlarms.remove(i);
-                }
-            } catch (RemoteException e) {
+            if (a.uid == uid) {
+                // Don't set didRemove, since this doesn't impact the scheduled alarms.
+                mPendingWhileIdleAlarms.remove(i);
             }
         }
 
@@ -2807,15 +2803,22 @@
         @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
         }
 
-        @Override public void onUidGone(int uid) throws RemoteException {
+        @Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
+            if (disabled) {
+                synchronized (mLock) {
+                    removeForStoppedLocked(uid);
+                }
+            }
         }
 
         @Override public void onUidActive(int uid) throws RemoteException {
         }
 
-        @Override public void onUidIdle(int uid) throws RemoteException {
-            synchronized (mLock) {
-                removeForStoppedLocked(uid);
+        @Override public void onUidIdle(int uid, boolean disabled) throws RemoteException {
+            if (disabled) {
+                synchronized (mLock) {
+                    removeForStoppedLocked(uid);
+                }
             }
         }
     };
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 6456048..9b3fac3 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1364,7 +1364,8 @@
                     try {
                         mBluetoothLock.writeLock().lock();
                         if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
-                            mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
+                            mBluetoothGatt = IBluetoothGatt.Stub
+                                    .asInterface(Binder.allowBlocking(service));
                             onBluetoothGattServiceUp();
                             break;
                         } // else must be SERVICE_IBLUETOOTH
@@ -1374,7 +1375,7 @@
 
                         mBinding = false;
                         mBluetoothBinder = service;
-                        mBluetooth = IBluetooth.Stub.asInterface(service);
+                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
 
                         if (!isNameAndAddressSet()) {
                             Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 553cb07..830a6ed 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -40,7 +40,7 @@
 import android.view.KeyEvent;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
 /**
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 2698f95..2bf5866 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -29,6 +29,7 @@
 import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
+import com.android.internal.os.TransferPipe;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethod;
@@ -4041,9 +4042,9 @@
         if (client != null) {
             pw.flush();
             try {
-                client.client.asBinder().dump(fd, args);
-            } catch (RemoteException e) {
-                p.println("Input method client dead: " + e);
+                TransferPipe.dumpAsync(client.client.asBinder(), fd, args);
+            } catch (IOException | RemoteException e) {
+                p.println("Failed to dump input method client: " + e);
             }
         } else {
             p.println("No input method client.");
@@ -4057,9 +4058,9 @@
             p.println(" ");
             pw.flush();
             try {
-                focusedWindowClient.client.asBinder().dump(fd, args);
-            } catch (RemoteException e) {
-                p.println("Input method client in focused window dead: " + e);
+                TransferPipe.dumpAsync(focusedWindowClient.client.asBinder(), fd, args);
+            } catch (IOException | RemoteException e) {
+                p.println("Failed to dump input method client in focused window: " + e);
             }
         }
 
@@ -4067,9 +4068,9 @@
         if (method != null) {
             pw.flush();
             try {
-                method.asBinder().dump(fd, args);
-            } catch (RemoteException e) {
-                p.println("Input method service dead: " + e);
+                TransferPipe.dumpAsync(method.asBinder(), fd, args);
+            } catch (IOException | RemoteException e) {
+                p.println("Failed to dump input method service: " + e);
             }
         } else {
             p.println("No input method service.");
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index a2207b2..dd342c5 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -49,6 +49,8 @@
 import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
 import android.os.ServiceManager;
@@ -79,6 +81,7 @@
 import libcore.util.HexEncoding;
 
 import java.io.ByteArrayOutputStream;
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -1585,6 +1588,31 @@
         return mStrongAuthTracker.getStrongAuthForUser(userId);
     }
 
+    private boolean isCallerShell() {
+        final int callingUid = Binder.getCallingUid();
+        return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+    }
+
+    private void enforceShell() {
+        if (!isCallerShell()) {
+            throw new SecurityException("Caller must be shell");
+        }
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
+            throws RemoteException {
+        enforceShell();
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            (new LockSettingsShellCommand(mContext, new LockPatternUtils(mContext))).exec(
+                    this, in, out, err, args, callback, resultReceiver);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
     private static final String[] VALID_SETTINGS = new String[] {
         LockPatternUtils.LOCKOUT_PERMANENT_KEY,
         LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
diff --git a/services/core/java/com/android/server/LockSettingsShellCommand.java b/services/core/java/com/android/server/LockSettingsShellCommand.java
new file mode 100644
index 0000000..0efdd51
--- /dev/null
+++ b/services/core/java/com/android/server/LockSettingsShellCommand.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+import static com.android.internal.widget.LockPatternUtils.stringToPattern;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
+
+class LockSettingsShellCommand extends ShellCommand {
+
+    private static final String COMMAND_SET_PATTERN = "set-pattern";
+    private static final String COMMAND_SET_PIN = "set-pin";
+    private static final String COMMAND_SET_PASSWORD = "set-password";
+    private static final String COMMAND_CLEAR = "clear";
+
+    private int mCurrentUserId;
+    private final LockPatternUtils mLockPatternUtils;
+    private final Context mContext;
+    private String mOld = "";
+    private String mNew = "";
+
+    LockSettingsShellCommand(Context context, LockPatternUtils lockPatternUtils) {
+        mContext = context;
+        mLockPatternUtils = lockPatternUtils;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        try {
+            mCurrentUserId = ActivityManagerNative.getDefault().getCurrentUser().id;
+
+            parseArgs();
+            if (!checkCredential()) {
+                return -1;
+            }
+            switch (cmd) {
+                case COMMAND_SET_PATTERN:
+                    runSetPattern();
+                    break;
+                case COMMAND_SET_PASSWORD:
+                    runSetPassword();
+                    break;
+                case COMMAND_SET_PIN:
+                    runSetPin();
+                    break;
+                case COMMAND_CLEAR:
+                    runClear();
+                    break;
+                default:
+                    getErrPrintWriter().println("Unknown command: " + cmd);
+                    break;
+            }
+            return 0;
+        } catch (Exception e) {
+            getErrPrintWriter().println("Error while executing command: " + e);
+            return -1;
+        }
+    }
+
+    @Override
+    public void onHelp() {
+    }
+
+    private void parseArgs() {
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if ("--old".equals(opt)) {
+                mOld = getNextArgRequired();
+            } else {
+                getErrPrintWriter().println("Unknown option: " + opt);
+                throw new IllegalArgumentException();
+            }
+        }
+        mNew = getNextArg();
+    }
+
+    private void runSetPattern() throws RemoteException {
+        mLockPatternUtils.saveLockPattern(stringToPattern(mNew), mOld, mCurrentUserId);
+        getOutPrintWriter().println("Pattern set to '" + mNew + "'");
+    }
+
+    private void runSetPassword() throws RemoteException {
+        mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_ALPHABETIC, mCurrentUserId);
+        getOutPrintWriter().println("Password set to '" + mNew + "'");
+    }
+
+    private void runSetPin() throws RemoteException {
+        mLockPatternUtils.saveLockPassword(mNew, mOld, PASSWORD_QUALITY_NUMERIC, mCurrentUserId);
+        getOutPrintWriter().println("Pin set to '" + mNew + "'");
+    }
+
+    private void runClear() throws RemoteException {
+        mLockPatternUtils.clearLock(mCurrentUserId);
+        getOutPrintWriter().println("Lock credential cleared");
+    }
+
+    private boolean checkCredential() throws RemoteException, RequestThrottledException {
+        final boolean havePassword = mLockPatternUtils.isLockPasswordEnabled(mCurrentUserId);
+        final boolean havePattern = mLockPatternUtils.isLockPatternEnabled(mCurrentUserId);
+        if (havePassword || havePattern) {
+            boolean result;
+            if (havePassword) {
+                result = mLockPatternUtils.checkPassword(mOld, mCurrentUserId);
+            } else {
+                result = mLockPatternUtils.checkPattern(stringToPattern(mOld),
+                        mCurrentUserId);
+            }
+            if (result) {
+                return true;
+            } else {
+                getOutPrintWriter().println("Old password '" + mOld + "' didn't match");
+                return false;
+            }
+        } else {
+            return true;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 33f9234..0414b47 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -92,7 +92,7 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             Slog.i(TAG, "MmsService connected");
             synchronized (MmsServiceBroker.this) {
-                mService = IMms.Stub.asInterface(service);
+                mService = IMms.Stub.asInterface(Binder.allowBlocking(service));
                 MmsServiceBroker.this.notifyAll();
             }
         }
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 83d6344..f5cda0a 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -42,8 +42,10 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.TransferPipe;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -418,12 +420,9 @@
 
         for (INetworkScoreCache scoreCache : getScoreCaches()) {
             try {
-                scoreCache.asBinder().dump(fd, args);
-            } catch (RemoteException e) {
-                writer.println("Unable to dump score cache");
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "Unable to dump score cache", e);
-                }
+                TransferPipe.dumpAsync(scoreCache.asBinder(), fd, args);
+            } catch (IOException | RemoteException e) {
+                writer.println("Failed to dump score cache: " + e);
             }
         }
         if (mServiceConnection != null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index dc4a52d..136e02c 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -348,7 +348,7 @@
                 // Before going further -- if this app is not allowed to run in the
                 // background, then at this point we aren't going to let it period.
                 final int allowed = mAm.checkAllowBackgroundLocked(
-                        r.appInfo.uid, r.packageName, callingPid, true);
+                        r.appInfo.uid, r.packageName, callingPid, false);
                 if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                     Slog.w(TAG, "Background start not allowed: service "
                             + service + " to " + r.name.flattenToShortString()
@@ -594,7 +594,8 @@
             for (int i=services.mServicesByName.size()-1; i>=0; i--) {
                 ServiceRecord service = services.mServicesByName.valueAt(i);
                 if (service.appInfo.uid == uid && service.startRequested) {
-                    if (mAm.mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
+                    if (service.appInfo.isEphemeralApp() ||
+                            mAm.mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
                             uid, service.packageName) != AppOpsManager.MODE_ALLOWED) {
                         if (stopping == null) {
                             stopping = new ArrayList<>();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 989977a..d60f115 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -291,7 +291,6 @@
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
-import static android.provider.Settings.Global.LENIENT_BACKGROUND_CHECK;
 import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
 import static android.provider.Settings.System.FONT_SCALE;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -1360,7 +1359,6 @@
     String mOrigDebugApp = null;
     boolean mOrigWaitForDebugger = false;
     boolean mAlwaysFinishActivities = false;
-    boolean mLenientBackgroundCheck = false;
     boolean mForceResizableActivities;
     boolean mSupportsMultiWindow;
     boolean mSupportsFreeformWindowManagement;
@@ -2736,7 +2734,8 @@
             for (int i=0; i<N; i++) {
                 Parcel data2 = Parcel.obtain();
                 try {
-                    procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null, 0);
+                    procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null,
+                            Binder.FLAG_ONEWAY);
                 } catch (RemoteException e) {
                 }
                 data2.recycle();
@@ -4148,7 +4147,7 @@
                             if ((reg.which & ActivityManager.UID_OBSERVER_IDLE) != 0) {
                                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                                         "UID idle uid=" + item.uid);
-                                observer.onUidIdle(item.uid);
+                                observer.onUidIdle(item.uid, item.ephemeral);
                             }
                             if (VALIDATE_UID_STATES && i == 0) {
                                 if (validateUid != null) {
@@ -4170,7 +4169,7 @@
                             if ((reg.which & ActivityManager.UID_OBSERVER_GONE) != 0) {
                                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                                         "UID gone uid=" + item.uid);
-                                observer.onUidGone(item.uid);
+                                observer.onUidGone(item.uid, item.ephemeral);
                             }
                             if (reg.lastProcStates != null) {
                                 reg.lastProcStates.delete(item.uid);
@@ -7837,38 +7836,43 @@
 
     public int getAppStartMode(int uid, String packageName) {
         synchronized (this) {
-            return checkAllowBackgroundLocked(uid, packageName, -1, true);
+            return checkAllowBackgroundLocked(uid, packageName, -1, false);
         }
     }
 
     int checkAllowBackgroundLocked(int uid, String packageName, int callingPid,
-            boolean allowWhenForeground) {
+            boolean alwaysRestrict) {
         UidRecord uidRec = mActiveUids.get(uid);
-        if (!mLenientBackgroundCheck) {
-            if (!allowWhenForeground || uidRec == null
-                    || uidRec.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
+        if (uidRec == null || alwaysRestrict || uidRec.idle) {
+            boolean ephemeral;
+            if (uidRec == null) {
+                ephemeral = getPackageManagerInternalLocked().isPackageEphemeral(
+                        UserHandle.getUserId(uid), packageName);
+            } else {
+                ephemeral = uidRec.ephemeral;
+            }
+
+            if (ephemeral) {
+                // We are hard-core about ephemeral apps not running in the background.
+                return ActivityManager.APP_START_MODE_DISABLED;
+            } else {
+                if (callingPid >= 0) {
+                    ProcessRecord proc;
+                    synchronized (mPidsSelfLocked) {
+                        proc = mPidsSelfLocked.get(callingPid);
+                    }
+                    if (proc != null && proc.curProcState
+                            < ActivityManager.PROCESS_STATE_RECEIVER) {
+                        // Whoever is instigating this is in the foreground, so we will allow it
+                        // to go through.
+                        return ActivityManager.APP_START_MODE_NORMAL;
+                    }
+                }
                 if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid,
                         packageName) != AppOpsManager.MODE_ALLOWED) {
                     return ActivityManager.APP_START_MODE_DELAYED;
                 }
             }
-
-        } else if (uidRec == null || uidRec.idle) {
-            if (callingPid >= 0) {
-                ProcessRecord proc;
-                synchronized (mPidsSelfLocked) {
-                    proc = mPidsSelfLocked.get(callingPid);
-                }
-                if (proc != null && proc.curProcState < ActivityManager.PROCESS_STATE_RECEIVER) {
-                    // Whoever is instigating this is in the foreground, so we will allow it
-                    // to go through.
-                    return ActivityManager.APP_START_MODE_NORMAL;
-                }
-            }
-            if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName)
-                    != AppOpsManager.MODE_ALLOWED) {
-                return ActivityManager.APP_START_MODE_DELAYED;
-            }
         }
         return ActivityManager.APP_START_MODE_NORMAL;
     }
@@ -11915,25 +11919,6 @@
     }
 
     @Override
-    public void setLenientBackgroundCheck(boolean enabled) {
-        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
-                "setLenientBackgroundCheck()");
-
-        long ident = Binder.clearCallingIdentity();
-        try {
-            Settings.Global.putInt(
-                    mContext.getContentResolver(),
-                    Settings.Global.LENIENT_BACKGROUND_CHECK, enabled ? 1 : 0);
-
-            synchronized (this) {
-                mLenientBackgroundCheck = enabled;
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    @Override
     public void setActivityController(IActivityController controller, boolean imAMonkey) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "setActivityController()");
@@ -13032,8 +13017,6 @@
         final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
         final boolean alwaysFinishActivities =
                 Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
-        final boolean lenientBackgroundCheck =
-                Settings.Global.getInt(resolver, LENIENT_BACKGROUND_CHECK, 0) != 0;
         final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
         final boolean forceResizable = Settings.Global.getInt(
                 resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
@@ -13054,7 +13037,6 @@
             mDebugApp = mOrigDebugApp = debugApp;
             mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
             mAlwaysFinishActivities = alwaysFinishActivities;
-            mLenientBackgroundCheck = lenientBackgroundCheck;
             mSupportsLeanbackOnly = supportsLeanbackOnly;
             mForceResizableActivities = forceResizable;
             if (supportsMultiWindow || forceResizable) {
@@ -14831,9 +14813,8 @@
             }
         }
         if (dumpPackage == null) {
-            if (mAlwaysFinishActivities || mLenientBackgroundCheck) {
-                pw.println("  mAlwaysFinishActivities=" + mAlwaysFinishActivities
-                        + " mLenientBackgroundCheck=" + mLenientBackgroundCheck);
+            if (mAlwaysFinishActivities) {
+                pw.println("  mAlwaysFinishActivities=" + mAlwaysFinishActivities);
             }
             if (mController != null) {
                 pw.println("  mController=" + mController
@@ -20758,6 +20739,7 @@
         pendingChange.change = change;
         pendingChange.processState = uidRec != null
                 ? uidRec.setProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
+        pendingChange.ephemeral = uidRec.ephemeral;
 
         // Directly update the power manager, since we sit on top of it and it is critical
         // it be kept in sync (so wake locks will be held as soon as appropriate).
@@ -21125,8 +21107,11 @@
                 } else {
                     // Keeping this process, update its uid.
                     final UidRecord uidRec = app.uidRecord;
-                    if (uidRec != null && uidRec.curProcState > app.curProcState) {
-                        uidRec.curProcState = app.curProcState;
+                    if (uidRec != null) {
+                        uidRec.ephemeral = app.info.isEphemeralApp();
+                        if (uidRec.curProcState > app.curProcState) {
+                            uidRec.curProcState = app.curProcState;
+                        }
                     }
                 }
 
@@ -21385,6 +21370,63 @@
         }
     }
 
+    @Override
+    public void makePackageIdle(String packageName, int userId) {
+        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: makePackageIdle() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        final int callingPid = Binder.getCallingPid();
+        userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(),
+                userId, true, ALLOW_FULL_ONLY, "makePackageIdle", null);
+        long callingId = Binder.clearCallingIdentity();
+        synchronized(this) {
+            try {
+                IPackageManager pm = AppGlobals.getPackageManager();
+                int pkgUid = -1;
+                try {
+                    pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES
+                            | MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM);
+                } catch (RemoteException e) {
+                }
+                if (pkgUid == -1) {
+                    throw new IllegalArgumentException("Unknown package name " + packageName);
+                }
+
+                if (mLocalPowerManager != null) {
+                    mLocalPowerManager.startUidChanges();
+                }
+                final int appId = UserHandle.getAppId(pkgUid);
+                final int N = mActiveUids.size();
+                for (int i=N-1; i>=0; i--) {
+                    final UidRecord uidRec = mActiveUids.valueAt(i);
+                    final long bgTime = uidRec.lastBackgroundTime;
+                    if (bgTime > 0 && !uidRec.idle) {
+                        if (UserHandle.getAppId(uidRec.uid) == appId) {
+                            if (userId == UserHandle.USER_ALL ||
+                                    userId == UserHandle.getUserId(uidRec.uid)) {
+                                uidRec.idle = true;
+                                Slog.w(TAG, "Idling uid " + UserHandle.formatUid(uidRec.uid)
+                                        + " from package " + packageName + " user " + userId);
+                                doStopUidLocked(uidRec.uid, uidRec);
+                            }
+                        }
+                    }
+                }
+            } finally {
+                if (mLocalPowerManager != null) {
+                    mLocalPowerManager.finishUidChanges();
+                }
+                Binder.restoreCallingIdentity(callingId);
+            }
+        }
+    }
+
     final void idleUids() {
         synchronized (this) {
             final int N = mActiveUids.size();
@@ -22206,6 +22248,15 @@
             // no need to synchronize(this) just to read & return the value
             return mSystemReady;
         }
+
+        @Override
+        public void notifyKeyguardTrustedChanged() {
+            synchronized (ActivityManagerService.this) {
+                if (mKeyguardController.isKeyguardShowing()) {
+                    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+                }
+            }
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index abeea74..52ad72d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -169,6 +169,8 @@
                     return runKill(pw);
                 case "kill-all":
                     return runKillAll(pw);
+                case "make-idle":
+                    return runMakeIdle(pw);
                 case "monitor":
                     return runMonitor(pw);
                 case "hang":
@@ -205,8 +207,6 @@
                     return runTrackAssociations(pw);
                 case "untrack-associations":
                     return runUntrackAssociations(pw);
-                case "lenient-background-check":
-                    return runLenientBackgroundCheck(pw);
                 case "get-uid-state":
                     return getUidState(pw);
                 case "get-config":
@@ -853,6 +853,22 @@
         return 0;
     }
 
+    int runMakeIdle(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_ALL;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        mInterface.makePackageIdle(getNextArgRequired(), userId);
+        return 0;
+    }
+
     static final class MyActivityController extends IActivityController.Stub {
         final IActivityManager mInterface;
         final PrintWriter mPw;
@@ -1432,22 +1448,6 @@
         return 0;
     }
 
-    int runLenientBackgroundCheck(PrintWriter pw) throws RemoteException {
-        String arg = getNextArg();
-        if (arg != null) {
-            boolean state = Boolean.valueOf(arg) || "1".equals(arg);
-            mInterface.setLenientBackgroundCheck(state);
-        }
-        synchronized (mInternal) {
-            if (mInternal.mLenientBackgroundCheck) {
-                pw.println("Lenient background check enabled");
-            } else {
-                pw.println("Lenient background check disabled");
-            }
-        }
-        return 0;
-    }
-
     int getUidState(PrintWriter pw) throws RemoteException {
         mInternal.enforceCallingPermission(android.Manifest.permission.DUMP,
                 "getUidState()");
@@ -2478,8 +2478,6 @@
             pw.println("      Enable association tracking.");
             pw.println("  untrack-associations");
             pw.println("      Disable and clear association tracking.");
-            pw.println("  lenient-background-check [<true|false>]");
-            pw.println("      Optionally controls lenient background check mode, returns current mode.");
             pw.println("  get-uid-state <UID>");
             pw.println("      Gets the process state of an app given its <UID>.");
             pw.println("  attach-agent <PROCESS> <FILE>");
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index be8f21d..facfeb6 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -16,7 +16,7 @@
 import android.util.Slog;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.util.ArrayList;
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 0d79980..1bdef43 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1806,8 +1806,9 @@
         final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing();
         final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
         final boolean showWhenLocked = r.hasShowWhenLockedWindows();
+        final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
         if (shouldBeVisible) {
-            if (r.hasDismissKeyguardWindows() && mTopDismissingKeyguardActivity == null) {
+            if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
                 mTopDismissingKeyguardActivity = r;
             }
 
@@ -1819,8 +1820,10 @@
         }
         if (keyguardShowing) {
 
-            // If keyguard is showing, nothing is visible.
-            return false;
+            // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
+            // right away.
+            return shouldBeVisible && mStackSupervisor.mKeyguardController
+                    .canShowActivityWhileKeyguardShowing(dismissKeyguard);
         } else if (keyguardLocked) {
 
             // Show when locked windows above keyguard.
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index e4ec169..691d6b9 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -458,9 +458,12 @@
         // Instead, launch the ephemeral installer. Once the installer is finished, it
         // starts either the intent we resolved here [on install error] or the ephemeral
         // app [on install success].
-        if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
+        if (rInfo != null && rInfo.ephemeralIntentInfo != null) {
+            final String packageName =
+                    rInfo.ephemeralIntentInfo.getEphemeralResolveInfo().getPackageName();
+            final String splitName = rInfo.ephemeralIntentInfo.getSplitName();
             intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
-                    rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
+                    packageName, splitName, callingPackage, resolvedType,
                     userId);
             resolvedType = null;
             callingUid = realCallingUid;
@@ -524,7 +527,8 @@
      * Builds and returns an intent to launch the ephemeral installer.
      */
     private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
-            String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
+            String ephemeralPackageName, String ephemeralSplitName, String callingPackage,
+            String resolvedType, int userId) {
         final Intent nonEphemeralIntent = new Intent(origIntent);
         nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
         // Intent that is launched if the ephemeral package couldn't be installed
@@ -540,7 +544,7 @@
         if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
             // Force the intent to be directed to the ephemeral package
             ephemeralIntent = new Intent(origIntent);
-            ephemeralIntent.setPackage(ephemeralPackage);
+            ephemeralIntent.setPackage(ephemeralPackageName);
         } else {
             // Success intent goes back to the installer
             ephemeralIntent = new Intent(launchIntent);
@@ -564,7 +568,8 @@
                 | Intent.FLAG_ACTIVITY_CLEAR_TASK
                 | Intent.FLAG_ACTIVITY_NO_HISTORY
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
+        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackageName);
+        intent.putExtra(Intent.EXTRA_SPLIT_NAME, ephemeralSplitName);
         intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
         intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
         // TODO: Remove when the platform has fully implemented ephemeral apps
@@ -1199,6 +1204,14 @@
                 // since the app transition will not be triggered through the resume channel.
                 mWindowManager.executeAppTransition();
             } else {
+                // If the target stack was not previously focusable (previous top running activity
+                // on that stack was not visible) then any prior calls to move the stack to the
+                // will not update the focused stack.  If starting the new activity now allows the
+                // task stack to be focusable, then ensure that we now update the focused stack
+                // accordingly.
+                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
+                    mTargetStack.moveToFront("startActivityUnchecked");
+                }
                 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                         mOptions);
             }
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index c19a571..7a122e6 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -18,7 +18,7 @@
 
 import com.android.internal.app.ProcessMap;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.server.Watchdog;
 
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index c6befd7..9e29725 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -17,7 +17,7 @@
 package com.android.server.am;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto;
 
 import android.content.ActivityNotFoundException;
 import android.content.Context;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 4e69162..8104a43 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -36,7 +36,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -595,8 +594,12 @@
         }
         if (!skip) {
             final int allowed = mService.checkAllowBackgroundLocked(filter.receiverList.uid,
-                    filter.packageName, -1, true);
-            if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
+                    filter.packageName, -1, false);
+            if (false && allowed == ActivityManager.APP_START_MODE_DISABLED) {
+                // XXX should we really not allow this?  It means that while we are
+                // keeping an ephemeral app cached, its registered receivers will stop
+                // receiving broadcasts after it goes idle...  so if it comes back to
+                // the foreground, it won't know what the current state of those broadcasts is.
                 Slog.w(TAG, "Background execution not allowed: receiving "
                         + r.intent
                         + " to " + filter.receiverList.app
@@ -1155,7 +1158,7 @@
             if (!skip) {
                 final int allowed = mService.checkAllowBackgroundLocked(
                         info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1,
-                        false);
+                        true);
                 if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                     // We won't allow this receiver to be launched if the app has been
                     // completely disabled from launches, or it was not explicitly sent
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 722974b..f618fc7 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -112,3 +112,5 @@
 # Report changing memory conditions (Values are ProcessStats.ADJ_MEM_FACTOR* constants)
 30050 am_mem_factor (Current|1|5),(Previous|1|5)
 
+# UserState has changed
+30051 am_user_state_changed (id|1|5),(state|1|5)
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 98acc9c..9d8c383 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -154,6 +154,14 @@
         }
     }
 
+    /**
+     * @return True if we may show an activity while Keyguard is showing because we are in the
+     *         process of dismissing it anyways, false otherwise.
+     */
+    boolean canShowActivityWhileKeyguardShowing(boolean dismissKeyguard) {
+        return dismissKeyguard && canDismissKeyguard();
+    }
+
     private void visibilitiesUpdated() {
         final boolean lastOccluded = mOccluded;
         final ActivityRecord lastDismissingKeyguardActivity = mDismissingKeyguardActivity;
@@ -215,7 +223,6 @@
                     && mWindowManager.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
                 mWindowManager.prepareAppTransition(mBeforeUnoccludeTransit,
                         false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */);
-                mKeyguardGoingAway = true;
                 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 mWindowManager.executeAppTransition();
             }
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index d24c3a5..d1a15bd 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -29,6 +29,7 @@
     int curProcState;
     int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
     long lastBackgroundTime;
+    boolean ephemeral;
     boolean idle;
     int numProcs;
 
@@ -43,6 +44,7 @@
         int uid;
         int change;
         int processState;
+        boolean ephemeral;
     }
 
     ChangeItem pendingChange;
@@ -64,6 +66,9 @@
         UserHandle.formatUid(sb, uid);
         sb.append(' ');
         sb.append(ProcessList.makeProcStateString(curProcState));
+        if (ephemeral) {
+            sb.append(" ephemeral");
+        }
         if (lastBackgroundTime > 0) {
             sb.append(" bg:");
             TimeUtils.formatDuration(SystemClock.elapsedRealtime()-lastBackgroundTime, sb);
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index 48238b6..42c31b1 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -70,6 +70,7 @@
     public boolean setState(int oldState, int newState) {
         if (state == oldState) {
             setState(newState);
+            EventLogTags.writeAmUserStateChanged(mHandle.getIdentifier(), newState);
             return true;
         } else {
             Slog.w(TAG, "Expected user " + mHandle.getIdentifier() + " in state "
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index f1d01e0..372b2d8 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -29,14 +29,14 @@
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
 import android.os.Parcelable;
-import com.android.server.connectivity.metrics.IpConnectivityLogClass;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityEvent;
-import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog;
-import static com.android.server.connectivity.metrics.IpConnectivityLogClass.NetworkId;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
 
 /** {@hide} */
 final public class IpConnectivityEventBuilder {
@@ -136,96 +136,107 @@
     }
 
     private static void setDhcpErrorEvent(IpConnectivityEvent out, DhcpErrorEvent in) {
-        out.dhcpEvent = new IpConnectivityLogClass.DHCPEvent();
-        out.dhcpEvent.ifName = in.ifName;
-        out.dhcpEvent.errorCode = in.errorCode;
+        IpConnectivityLogClass.DHCPEvent dhcpEvent = new IpConnectivityLogClass.DHCPEvent();
+        dhcpEvent.ifName = in.ifName;
+        dhcpEvent.setErrorCode(in.errorCode);
+        out.setDhcpEvent(dhcpEvent);
     }
 
     private static void setDhcpClientEvent(IpConnectivityEvent out, DhcpClientEvent in) {
-        out.dhcpEvent = new IpConnectivityLogClass.DHCPEvent();
-        out.dhcpEvent.ifName = in.ifName;
-        out.dhcpEvent.stateTransition = in.msg;
-        out.dhcpEvent.durationMs = in.durationMs;
+        IpConnectivityLogClass.DHCPEvent dhcpEvent = new IpConnectivityLogClass.DHCPEvent();
+        dhcpEvent.ifName = in.ifName;
+        dhcpEvent.setStateTransition(in.msg);
+        dhcpEvent.durationMs = in.durationMs;
+        out.setDhcpEvent(dhcpEvent);
     }
 
     private static void setDnsEvent(IpConnectivityEvent out, DnsEvent in) {
-        out.dnsLookupBatch = new IpConnectivityLogClass.DNSLookupBatch();
-        out.dnsLookupBatch.networkId = netIdOf(in.netId);
-        out.dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
-        out.dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
-        out.dnsLookupBatch.latenciesMs = in.latenciesMs;
+        IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch = new IpConnectivityLogClass.DNSLookupBatch();
+        dnsLookupBatch.networkId = netIdOf(in.netId);
+        dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
+        dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
+        dnsLookupBatch.latenciesMs = in.latenciesMs;
+        out.setDnsLookupBatch(dnsLookupBatch);
     }
 
     private static void setIpManagerEvent(IpConnectivityEvent out, IpManagerEvent in) {
-        out.ipProvisioningEvent = new IpConnectivityLogClass.IpProvisioningEvent();
-        out.ipProvisioningEvent.ifName = in.ifName;
-        out.ipProvisioningEvent.eventType = in.eventType;
-        out.ipProvisioningEvent.latencyMs = (int) in.durationMs;
+        IpConnectivityLogClass.IpProvisioningEvent ipProvisioningEvent = new IpConnectivityLogClass.IpProvisioningEvent();
+        ipProvisioningEvent.ifName = in.ifName;
+        ipProvisioningEvent.eventType = in.eventType;
+        ipProvisioningEvent.latencyMs = (int) in.durationMs;
+        out.setIpProvisioningEvent(ipProvisioningEvent);
     }
 
     private static void setIpReachabilityEvent(IpConnectivityEvent out, IpReachabilityEvent in) {
-        out.ipReachabilityEvent = new IpConnectivityLogClass.IpReachabilityEvent();
-        out.ipReachabilityEvent.ifName = in.ifName;
-        out.ipReachabilityEvent.eventType = in.eventType;
+        IpConnectivityLogClass.IpReachabilityEvent ipReachabilityEvent = new IpConnectivityLogClass.IpReachabilityEvent();
+        ipReachabilityEvent.ifName = in.ifName;
+        ipReachabilityEvent.eventType = in.eventType;
+        out.setIpReachabilityEvent(ipReachabilityEvent);
     }
 
     private static void setDefaultNetworkEvent(IpConnectivityEvent out, DefaultNetworkEvent in) {
-        out.defaultNetworkEvent = new IpConnectivityLogClass.DefaultNetworkEvent();
-        out.defaultNetworkEvent.networkId = netIdOf(in.netId);
-        out.defaultNetworkEvent.previousNetworkId = netIdOf(in.prevNetId);
-        out.defaultNetworkEvent.transportTypes = in.transportTypes;
-        out.defaultNetworkEvent.previousNetworkIpSupport = ipSupportOf(in);
+        IpConnectivityLogClass.DefaultNetworkEvent defaultNetworkEvent = new IpConnectivityLogClass.DefaultNetworkEvent();
+        defaultNetworkEvent.networkId = netIdOf(in.netId);
+        defaultNetworkEvent.previousNetworkId = netIdOf(in.prevNetId);
+        defaultNetworkEvent.transportTypes = in.transportTypes;
+        defaultNetworkEvent.previousNetworkIpSupport = ipSupportOf(in);
+        out.setDefaultNetworkEvent(defaultNetworkEvent);
     }
 
     private static void setNetworkEvent(IpConnectivityEvent out, NetworkEvent in) {
-        out.networkEvent = new IpConnectivityLogClass.NetworkEvent();
-        out.networkEvent.networkId = netIdOf(in.netId);
-        out.networkEvent.eventType = in.eventType;
-        out.networkEvent.latencyMs = (int) in.durationMs;
+        IpConnectivityLogClass.NetworkEvent networkEvent = new IpConnectivityLogClass.NetworkEvent();
+        networkEvent.networkId = netIdOf(in.netId);
+        networkEvent.eventType = in.eventType;
+        networkEvent.latencyMs = (int) in.durationMs;
+        out.setNetworkEvent(networkEvent);
     }
 
     private static void setValidationProbeEvent(IpConnectivityEvent out, ValidationProbeEvent in) {
-        out.validationProbeEvent = new IpConnectivityLogClass.ValidationProbeEvent();
-        out.validationProbeEvent.networkId = netIdOf(in.netId);
-        out.validationProbeEvent.latencyMs = (int) in.durationMs;
-        out.validationProbeEvent.probeType = in.probeType;
-        out.validationProbeEvent.probeResult = in.returnCode;
+        IpConnectivityLogClass.ValidationProbeEvent validationProbeEvent = new IpConnectivityLogClass.ValidationProbeEvent();
+        validationProbeEvent.networkId = netIdOf(in.netId);
+        validationProbeEvent.latencyMs = (int) in.durationMs;
+        validationProbeEvent.probeType = in.probeType;
+        validationProbeEvent.probeResult = in.returnCode;
+        out.setValidationProbeEvent(validationProbeEvent);
     }
 
     private static void setApfProgramEvent(IpConnectivityEvent out, ApfProgramEvent in) {
-        out.apfProgramEvent = new IpConnectivityLogClass.ApfProgramEvent();
-        out.apfProgramEvent.lifetime = in.lifetime;
-        out.apfProgramEvent.filteredRas = in.filteredRas;
-        out.apfProgramEvent.currentRas = in.currentRas;
-        out.apfProgramEvent.programLength = in.programLength;
+        IpConnectivityLogClass.ApfProgramEvent apfProgramEvent = new IpConnectivityLogClass.ApfProgramEvent();
+        apfProgramEvent.lifetime = in.lifetime;
+        apfProgramEvent.filteredRas = in.filteredRas;
+        apfProgramEvent.currentRas = in.currentRas;
+        apfProgramEvent.programLength = in.programLength;
         if (isBitSet(in.flags, ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)) {
-            out.apfProgramEvent.dropMulticast = true;
+            apfProgramEvent.dropMulticast = true;
         }
         if (isBitSet(in.flags, ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)) {
-            out.apfProgramEvent.hasIpv4Addr = true;
+            apfProgramEvent.hasIpv4Addr = true;
         }
+        out.setApfProgramEvent(apfProgramEvent);
     }
 
     private static void setApfStats(IpConnectivityEvent out, ApfStats in) {
-        out.apfStatistics = new IpConnectivityLogClass.ApfStatistics();
-        out.apfStatistics.durationMs = in.durationMs;
-        out.apfStatistics.receivedRas = in.receivedRas;
-        out.apfStatistics.matchingRas = in.matchingRas;
-        out.apfStatistics.droppedRas = in.droppedRas;
-        out.apfStatistics.zeroLifetimeRas = in.zeroLifetimeRas;
-        out.apfStatistics.parseErrors = in.parseErrors;
-        out.apfStatistics.programUpdates = in.programUpdates;
-        out.apfStatistics.maxProgramSize = in.maxProgramSize;
+        IpConnectivityLogClass.ApfStatistics apfStatistics = new IpConnectivityLogClass.ApfStatistics();
+        apfStatistics.durationMs = in.durationMs;
+        apfStatistics.receivedRas = in.receivedRas;
+        apfStatistics.matchingRas = in.matchingRas;
+        apfStatistics.droppedRas = in.droppedRas;
+        apfStatistics.zeroLifetimeRas = in.zeroLifetimeRas;
+        apfStatistics.parseErrors = in.parseErrors;
+        apfStatistics.programUpdates = in.programUpdates;
+        apfStatistics.maxProgramSize = in.maxProgramSize;
+        out.setApfStatistics(apfStatistics);
     }
 
     private static void setRaEvent(IpConnectivityEvent out, RaEvent in) {
-        out.raEvent = new IpConnectivityLogClass.RaEvent();
-        out.raEvent.routerLifetime = in.routerLifetime;
-        out.raEvent.prefixValidLifetime = in.prefixValidLifetime;
-        out.raEvent.prefixPreferredLifetime = in.prefixPreferredLifetime;
-        out.raEvent.routeInfoLifetime = in.routeInfoLifetime;
-        out.raEvent.rdnssLifetime = in.rdnssLifetime;
-        out.raEvent.dnsslLifetime = in.dnsslLifetime;
+        IpConnectivityLogClass.RaEvent raEvent = new IpConnectivityLogClass.RaEvent();
+        raEvent.routerLifetime = in.routerLifetime;
+        raEvent.prefixValidLifetime = in.prefixValidLifetime;
+        raEvent.prefixPreferredLifetime = in.prefixPreferredLifetime;
+        raEvent.routeInfoLifetime = in.routeInfoLifetime;
+        raEvent.rdnssLifetime = in.rdnssLifetime;
+        raEvent.dnsslLifetime = in.dnsslLifetime;
+        out.setRaEvent(raEvent);
     }
 
     private static int[] bytesToInts(byte[] in) {
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index 641c62f..42f439c 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -42,7 +42,7 @@
 import java.util.ArrayList;
 import java.util.function.ToIntFunction;
 
-import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityEvent;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 
 /** {@hide} */
 final public class IpConnectivityMetrics extends SystemService {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 0beb227..6d96a10 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -71,6 +71,7 @@
 import com.android.internal.util.StateMachine;
 import com.android.server.connectivity.tethering.IControlsTethering;
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
+import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices;
 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
 import com.android.server.net.BaseNetworkObserver;
 
@@ -1939,7 +1940,8 @@
     private void trackNewTetherableInterface(String iface, int interfaceType) {
         TetherState tetherState;
         tetherState = new TetherState(new TetherInterfaceStateMachine(iface, mLooper,
-                interfaceType, mNMService, mStatsService, this));
+                interfaceType, mNMService, mStatsService, this,
+                new IPv6TetheringInterfaceServices(iface, mNMService)));
         mTetherStates.put(iface, tetherState);
         tetherState.mStateMachine.start();
     }
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
index c2c1a8c..dec2f77 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -45,7 +45,7 @@
 /**
  * @hide
  */
-class IPv6TetheringInterfaceServices {
+public class IPv6TetheringInterfaceServices {
     private static final String TAG = IPv6TetheringInterfaceServices.class.getSimpleName();
     private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
     private static final int RFC7421_IP_PREFIX_LENGTH = 64;
@@ -59,7 +59,7 @@
     private RouterAdvertisementDaemon mRaDaemon;
     private RaParams mLastRaParams;
 
-    IPv6TetheringInterfaceServices(String ifname, INetworkManagementService nms) {
+    public IPv6TetheringInterfaceServices(String ifname, INetworkManagementService nms) {
         mIfName = ifname;
         mNMService = nms;
     }
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 6ca4e27..37221a9 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -94,14 +94,14 @@
 
     public TetherInterfaceStateMachine(String ifaceName, Looper looper, int interfaceType,
                     INetworkManagementService nMService, INetworkStatsService statsService,
-                    IControlsTethering tetherController) {
+                    IControlsTethering tetherController, IPv6TetheringInterfaceServices ipv6Svc) {
         super(ifaceName, looper);
         mNMService = nMService;
         mStatsService = statsService;
         mTetherController = tetherController;
         mIfaceName = ifaceName;
         mInterfaceType = interfaceType;
-        mIPv6TetherSvc = new IPv6TetheringInterfaceServices(mIfaceName, mNMService);
+        mIPv6TetherSvc = ipv6Svc;
         mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
 
         mInitialState = new InitialState();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 971989b..9c762cc 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -220,6 +220,11 @@
     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
 
+    // The default color mode for default displays. Overrides the usual
+    // Display.Display.COLOR_MODE_DEFAULT for displays with the
+    // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
+    private final int mDefaultDisplayDefaultColorMode;
+
     // Temporary list of deferred work to perform when setting the display state.
     // Only used by requestDisplayState.  The field is self-synchronized and only
     // intended for use inside of the requestGlobalDisplayStateInternal function.
@@ -232,6 +237,8 @@
         mUiHandler = UiThread.getHandler();
         mDisplayAdapterListener = new DisplayAdapterListener();
         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
+        mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
+            com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
 
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
@@ -703,6 +710,14 @@
         }
         if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
             int colorMode = mPersistentDataStore.getColorMode(device);
+            if (colorMode == Display.COLOR_MODE_INVALID) {
+                if ((device.getDisplayDeviceInfoLocked().flags
+                     & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
+                    colorMode = mDefaultDisplayDefaultColorMode;
+                } else {
+                    colorMode = Display.COLOR_MODE_DEFAULT;
+                }
+            }
             display.setRequestedColorModeLocked(colorMode);
         }
         scheduleTraversalLocked(false);
@@ -1043,6 +1058,7 @@
             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
             pw.println("  mDefaultViewport=" + mDefaultViewport);
             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
+            pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
             pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
 
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 5616fb9..47701b9 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -183,11 +183,11 @@
 
     public int getColorMode(DisplayDevice device) {
         if (!device.hasStableUniqueId()) {
-            return Display.COLOR_MODE_DEFAULT;
+            return Display.COLOR_MODE_INVALID;
         }
         DisplayState state = getDisplayState(device.getUniqueId(), false);
         if (state == null) {
-            return Display.COLOR_MODE_DEFAULT;
+            return Display.COLOR_MODE_INVALID;
         }
         return state.getColorMode();
     }
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 393199d..fbad8de 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -17,7 +17,7 @@
 package com.android.server.dreams;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import android.content.ComponentName;
 import android.content.Context;
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 5297589..d65e257 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -17,7 +17,7 @@
 package com.android.server.fingerprint;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import android.content.Context;
 import android.hardware.fingerprint.Fingerprint;
diff --git a/services/core/java/com/android/server/fingerprint/EnrollClient.java b/services/core/java/com/android/server/fingerprint/EnrollClient.java
index 640a46f..c70ca7f 100644
--- a/services/core/java/com/android/server/fingerprint/EnrollClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnrollClient.java
@@ -25,7 +25,7 @@
 import android.util.Slog;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.util.Arrays;
 
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index df64447..b878099 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -426,7 +426,7 @@
                                             Slog.d(TAG, "Removing jobs for package " + pkgName
                                                     + " in user " + userId);
                                         }
-                                        cancelJobsForUid(pkgUid, true);
+                                        cancelJobsForUid(pkgUid);
                                     }
                                 } catch (RemoteException|IllegalArgumentException e) {
                                     /*
@@ -455,7 +455,7 @@
                     if (DEBUG) {
                         Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
                     }
-                    cancelJobsForUid(uidRemoved, true);
+                    cancelJobsForUid(uidRemoved);
                 }
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
@@ -509,15 +509,20 @@
             updateUidState(uid, procState);
         }
 
-        @Override public void onUidGone(int uid) throws RemoteException {
+        @Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
             updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+            if (disabled) {
+                cancelJobsForUid(uid);
+            }
         }
 
         @Override public void onUidActive(int uid) throws RemoteException {
         }
 
-        @Override public void onUidIdle(int uid) throws RemoteException {
-            cancelJobsForUid(uid, false);
+        @Override public void onUidIdle(int uid, boolean disabled) throws RemoteException {
+            if (disabled) {
+                cancelJobsForUid(uid);
+            }
         }
     };
 
@@ -646,26 +651,15 @@
      * This will remove the job from the master list, and cancel the job if it was staged for
      * execution or being executed.
      * @param uid Uid to check against for removal of a job.
-     * @param forceAll If true, all jobs for the uid will be canceled; if false, only those
-     * whose apps are stopped.
+     *
      */
-    public void cancelJobsForUid(int uid, boolean forceAll) {
+    public void cancelJobsForUid(int uid) {
         List<JobStatus> jobsForUid;
         synchronized (mLock) {
             jobsForUid = mJobs.getJobsByUid(uid);
         }
         for (int i=0; i<jobsForUid.size(); i++) {
             JobStatus toRemove = jobsForUid.get(i);
-            if (!forceAll) {
-                String packageName = toRemove.getServiceComponent().getPackageName();
-                try {
-                    if (ActivityManagerNative.getDefault().getAppStartMode(uid, packageName)
-                            != ActivityManager.APP_START_MODE_DISABLED) {
-                        continue;
-                    }
-                } catch (RemoteException e) {
-                }
-            }
             cancelJobImpl(toRemove, null);
         }
     }
@@ -1698,7 +1692,7 @@
 
             long ident = Binder.clearCallingIdentity();
             try {
-                JobSchedulerService.this.cancelJobsForUid(uid, true);
+                JobSchedulerService.this.cancelJobsForUid(uid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 5eb06ed..b44087c 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -17,6 +17,7 @@
 package com.android.server.location;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 
 import android.content.Context;
@@ -30,6 +31,7 @@
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ILocationProvider;
 import com.android.internal.location.ProviderRequest;
+import com.android.internal.os.TransferPipe;
 import com.android.server.LocationManagerService;
 import com.android.server.ServiceWatcher;
 
@@ -230,14 +232,9 @@
         pw.flush();
 
         try {
-            service.asBinder().dump(fd, args);
-        } catch (RemoteException e) {
-            pw.println("service down (RemoteException)");
-            Log.w(TAG, e);
-        } catch (Exception e) {
-            pw.println("service down (Exception)");
-            // never let remote service crash system server
-            Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
+            TransferPipe.dumpAsync(service.asBinder(), fd, args);
+        } catch (IOException | RemoteException e) {
+            pw.println("Failed to dump location provider: " + e);
         }
     }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index fd99f57..c1506b9 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -689,7 +689,7 @@
             }
         }
 
-        @Override public void onUidGone(int uid) throws RemoteException {
+        @Override public void onUidGone(int uid, boolean disabled) throws RemoteException {
             synchronized (mUidRulesFirstLock) {
                 removeUidStateUL(uid);
             }
@@ -698,7 +698,7 @@
         @Override public void onUidActive(int uid) throws RemoteException {
         }
 
-        @Override public void onUidIdle(int uid) throws RemoteException {
+        @Override public void onUidIdle(int uid, boolean disabled) throws RemoteException {
         }
     };
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f3ae2bc..c7f4d6b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,25 +16,24 @@
 
 package com.android.server.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL;
-import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL_ALL;
-import static android.service.notification.NotificationRankerService.REASON_CHANNEL_BANNED;
-import static android.service.notification.NotificationRankerService.REASON_DELEGATE_CANCEL;
-import static android.service.notification.NotificationRankerService.REASON_DELEGATE_CANCEL_ALL;
-import static android.service.notification.NotificationRankerService.REASON_DELEGATE_CLICK;
-import static android.service.notification.NotificationRankerService.REASON_DELEGATE_ERROR;
-import static android.service.notification.NotificationRankerService.REASON_GROUP_SUMMARY_CANCELED;
-import static android.service.notification.NotificationRankerService.REASON_LISTENER_CANCEL;
-import static android.service.notification.NotificationRankerService.REASON_LISTENER_CANCEL_ALL;
-import static android.service.notification.NotificationRankerService.REASON_PACKAGE_BANNED;
-import static android.service.notification.NotificationRankerService.REASON_PACKAGE_CHANGED;
-import static android.service.notification.NotificationRankerService.REASON_PACKAGE_SUSPENDED;
-import static android.service.notification.NotificationRankerService.REASON_PROFILE_TURNED_OFF;
-import static android.service.notification.NotificationRankerService.REASON_SNOOZED;
-import static android.service.notification.NotificationRankerService.REASON_UNAUTOBUNDLED;
-import static android.service.notification.NotificationRankerService.REASON_USER_STOPPED;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_DELEGATE_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_DELEGATE_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_DELEGATE_CLICK;
+import static android.service.notification.NotificationListenerService.REASON_DELEGATE_ERROR;
+import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationListenerService.REASON_PACKAGE_SUSPENDED;
+import static android.service.notification.NotificationListenerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationListenerService.REASON_SNOOZED;
+import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
+import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS;
@@ -110,7 +109,7 @@
 import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
 import android.service.notification.IStatusBarNotificationHolder;
-import android.service.notification.NotificationRankerService;
+import android.service.notification.NotificationAssistantService;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRankingUpdate;
 import android.service.notification.StatusBarNotification;
@@ -125,7 +124,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
-import android.view.WindowManager;
 import android.view.WindowManagerInternal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -169,12 +167,10 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 /** {@hide} */
@@ -229,7 +225,6 @@
     /** notification_enqueue status value for an ignored notification. */
     private static final int EVENTLOG_ENQUEUE_STATUS_IGNORED = 2;
     private static final long MIN_PACKAGE_OVERRATE_LOG_INTERVAL = 5000; // milliseconds
-    private String mRankerServicePackageName;
 
     private IActivityManager mAm;
     AudioManager mAudioManager;
@@ -301,7 +296,7 @@
 
     private final UserProfiles mUserProfiles = new UserProfiles();
     private NotificationListeners mListeners;
-    private NotificationRankers mRankerServices;
+    private NotificationAssistants mNotificationAssistants;
     private ConditionProviders mConditionProviders;
     private NotificationUsageStats mUsageStats;
 
@@ -758,7 +753,7 @@
                     }
                 }
                 mListeners.onPackagesChanged(removingPackage, pkgList);
-                mRankerServices.onPackagesChanged(removingPackage, pkgList);
+                mNotificationAssistants.onPackagesChanged(removingPackage, pkgList);
                 mConditionProviders.onPackagesChanged(removingPackage, pkgList);
                 mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList);
             }
@@ -808,7 +803,7 @@
                 // Refresh managed services
                 mConditionProviders.onUserSwitched(user);
                 mListeners.onUserSwitched(user);
-                mRankerServices.onUserSwitched(user);
+                mNotificationAssistants.onUserSwitched(user);
                 mZenModeHelper.onUserSwitched(user);
             } else if (action.equals(Intent.ACTION_USER_ADDED)) {
                 mUserProfiles.updateCache(context);
@@ -819,7 +814,7 @@
                 final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                 mConditionProviders.onUserUnlocked(user);
                 mListeners.onUserUnlocked(user);
-                mRankerServices.onUserUnlocked(user);
+                mNotificationAssistants.onUserUnlocked(user);
                 mZenModeHelper.onUserUnlocked(user);
             }
         }
@@ -962,10 +957,6 @@
         mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
         mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
 
-        // This is the package that contains the AOSP framework update.
-        mRankerServicePackageName = getContext().getPackageManager()
-                .getServicesSystemSharedLibraryPackageName();
-
         mHandler = new WorkerHandler();
         mRankingThread.start();
         String[] extractorNames;
@@ -1059,10 +1050,8 @@
         // This is a MangedServices object that keeps track of the listeners.
         mListeners = new NotificationListeners();
 
-        // This is a MangedServices object that keeps track of the ranker.
-        mRankerServices = new NotificationRankers();
-        // Find the updatable ranker and register it.
-        mRankerServices.registerRanker();
+        // This is a MangedServices object that keeps track of the assistant.
+        mNotificationAssistants = new NotificationAssistants();
 
         mStatusBar = getLocalService(StatusBarManagerInternal.class);
         if (mStatusBar != null) {
@@ -1209,7 +1198,7 @@
             // bind to listener services.
             mSettingsObserver.observe();
             mListeners.onBootPhaseAppsCanStart();
-            mRankerServices.onBootPhaseAppsCanStart();
+            mNotificationAssistants.onBootPhaseAppsCanStart();
             mConditionProviders.onBootPhaseAppsCanStart();
         }
     }
@@ -1682,10 +1671,10 @@
                         final StatusBarNotification sbnOut = new StatusBarNotification(
                                 sbn.getPackageName(),
                                 sbn.getOpPkg(),
+                                sbn.getNotificationChannel(),
                                 sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(),
-                                0, // hide score from apps
                                 sbn.getNotification().clone(),
-                                sbn.getUser(), sbn.getPostTime());
+                                sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime());
                         list.add(sbnOut);
                     }
                 }
@@ -1791,8 +1780,8 @@
             long identity = Binder.clearCallingIdentity();
             try {
                 ManagedServices manager =
-                        mRankerServices.isComponentEnabledForCurrentProfiles(component)
-                        ? mRankerServices
+                        mNotificationAssistants.isComponentEnabledForCurrentProfiles(component)
+                        ? mNotificationAssistants
                         : mListeners;
                 manager.setComponentState(component, true);
             } finally {
@@ -2358,12 +2347,12 @@
         }
 
         @Override
-        public void applyAdjustmentFromRankerService(INotificationListener token,
+        public void applyAdjustmentFromAssistantService(INotificationListener token,
                 Adjustment adjustment) throws RemoteException {
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    mRankerServices.checkServiceTokenLocked(token);
+                    mNotificationAssistants.checkServiceTokenLocked(token);
                     applyAdjustmentLocked(adjustment);
                 }
                 mRankingHandler.requestSort();
@@ -2373,13 +2362,13 @@
         }
 
         @Override
-        public void applyAdjustmentsFromRankerService(INotificationListener token,
+        public void applyAdjustmentsFromAssistantService(INotificationListener token,
                 List<Adjustment> adjustments) throws RemoteException {
 
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    mRankerServices.checkServiceTokenLocked(token);
+                    mNotificationAssistants.checkServiceTokenLocked(token);
                     for (Adjustment adjustment : adjustments) {
                         applyAdjustmentLocked(adjustment);
                     }
@@ -2478,15 +2467,14 @@
                 }
                 final StatusBarNotification summarySbn =
                         new StatusBarNotification(adjustedSbn.getPackageName(),
-                                adjustedSbn.getOpPkg(), Integer.MAX_VALUE,
+                                adjustedSbn.getOpPkg(),
+                                adjustedSbn.getNotificationChannel(),
+                                Integer.MAX_VALUE,
                                 GroupHelper.AUTOGROUP_KEY, adjustedSbn.getUid(),
                                 adjustedSbn.getInitialPid(), summaryNotification,
                                 adjustedSbn.getUser(), GroupHelper.AUTOGROUP_KEY,
                                 System.currentTimeMillis());
-                summaryRecord = new NotificationRecord(getContext(), summarySbn,
-                        mRankingHelper.getNotificationChannel(adjustedSbn.getPackageName(),
-                                adjustedSbn.getUid(),
-                                adjustedSbn.getNotification().getNotificationChannel()));
+                summaryRecord = new NotificationRecord(getContext(), summarySbn);
                 summaries.put(pkg, summarySbn.getKey());
             }
         }
@@ -2632,9 +2620,8 @@
                     }
                 }
                 pw.println(')');
-                pw.println("\n  mRankerServicePackageName: " + mRankerServicePackageName);
-                pw.println("\n  Notification ranker services:");
-                mRankerServices.dump(pw, filter);
+                pw.println("\n  Notification assistant services:");
+                mNotificationAssistants.dump(pw, filter);
             }
 
             if (!zenOnly) {
@@ -2734,9 +2721,11 @@
             throw new IllegalArgumentException("null not allowed: pkg=" + pkg
                     + " id=" + id + " notification=" + notification);
         }
+        final NotificationChannel channel =  mRankingHelper.getNotificationChannelWithFallback(pkg,
+                callingUid, notification.getNotificationChannel());
         final StatusBarNotification n = new StatusBarNotification(
-                pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
-                user);
+                pkg, opPkg, channel, id, tag, callingUid, callingPid, notification,
+                user, null, System.currentTimeMillis());
 
         // Limit the number of notifications that any given package except the android
         // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
@@ -2799,9 +2788,7 @@
                 Notification.PRIORITY_MAX);
 
         // setup local book-keeping
-        final NotificationRecord r = new NotificationRecord(getContext(), n,
-                mRankingHelper.getNotificationChannelWithFallback(pkg, callingUid,
-                        n.getNotification().getNotificationChannel()));
+        final NotificationRecord r = new NotificationRecord(getContext(), n);
         mHandler.post(new EnqueueNotificationRunnable(userId, r));
 
         idOut[0] = id;
@@ -2885,9 +2872,9 @@
                     }
                 }
 
-                // tell the ranker service about the notification
-                if (mRankerServices.isEnabled()) {
-                    mRankerServices.onNotificationEnqueued(r);
+                // tell the assistant service about the notification
+                if (mNotificationAssistants.isEnabled()) {
+                    mNotificationAssistants.onNotificationEnqueued(r);
                     // TODO delay the code below here for 100ms or until there is an answer
                 }
 
@@ -2930,7 +2917,8 @@
                 } else {
                     Slog.e(TAG, "Not posting notification without small icon: " + notification);
                     if (old != null && !old.isCanceled) {
-                        mListeners.notifyRemovedLocked(n);
+                        mListeners.notifyRemovedLocked(n,
+                                NotificationListenerService.REASON_DELEGATE_ERROR);
                         mHandler.post(new Runnable() {
                             @Override
                             public void run() {
@@ -3542,7 +3530,7 @@
         // status bar
         if (r.getNotification().getSmallIcon() != null) {
             r.isCanceled = true;
-            mListeners.notifyRemovedLocked(r.sbn);
+            mListeners.notifyRemovedLocked(r.sbn, reason);
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -4075,19 +4063,19 @@
         }
     }
 
-    public class NotificationRankers extends ManagedServices {
+    public class NotificationAssistants extends ManagedServices {
 
-        public NotificationRankers() {
+        public NotificationAssistants() {
             super(getContext(), mHandler, mNotificationList, mUserProfiles);
         }
 
         @Override
         protected Config getConfig() {
             Config c = new Config();
-            c.caption = "notification ranker service";
-            c.serviceInterface = NotificationRankerService.SERVICE_INTERFACE;
-            c.secureSettingName = null;
-            c.bindPermission = Manifest.permission.BIND_NOTIFICATION_RANKER_SERVICE;
+            c.caption = "notification assistant service";
+            c.serviceInterface = NotificationAssistantService.SERVICE_INTERFACE;
+            c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT;
+            c.bindPermission = Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE;
             c.settingsAction = Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS;
             c.clientLabel = R.string.notification_ranker_binding_label;
             return c;
@@ -4117,10 +4105,10 @@
             final StatusBarNotification sbn = r.sbn;
             TrimCache trimCache = new TrimCache(sbn);
 
-            // mServices is the list inside ManagedServices of all the rankers,
+            // mServices is the list inside ManagedServices of all the assistants,
             // There should be only one, but it's a list, so while we enforce
             // singularity elsewhere, we keep it general here, to avoid surprises.
-            for (final ManagedServiceInfo info : NotificationRankers.this.mServices) {
+            for (final ManagedServiceInfo info : NotificationAssistants.this.mServices) {
                 boolean sbnVisible = isVisibleToListener(sbn, info);
                 if (!sbnVisible) {
                     continue;
@@ -4140,68 +4128,18 @@
 
         private void notifyEnqueued(final ManagedServiceInfo info,
                 final StatusBarNotification sbn, int importance, boolean fromUser) {
-            final INotificationListener ranker = (INotificationListener) info.service;
+            final INotificationListener assistant = (INotificationListener) info.service;
             StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                ranker.onNotificationEnqueued(sbnHolder, importance, fromUser);
+                assistant.onNotificationEnqueued(sbnHolder, importance, fromUser);
             } catch (RemoteException ex) {
-                Log.e(TAG, "unable to notify ranker (enqueued): " + ranker, ex);
+                Log.e(TAG, "unable to notify assistant (enqueued): " + assistant, ex);
             }
         }
 
         public boolean isEnabled() {
             return !mServices.isEmpty();
         }
-
-        @Override
-        public void onUserSwitched(int user) {
-            synchronized (mNotificationList) {
-                int i = mServices.size()-1;
-                while (i --> 0) {
-                    final ManagedServiceInfo info = mServices.get(i);
-                    unregisterService(info.service, info.userid);
-                }
-            }
-            registerRanker();
-        }
-
-        @Override
-        public void onPackagesChanged(boolean removingPackage, String[] pkgList) {
-            if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
-                    + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)));
-            if (mRankerServicePackageName == null) {
-                return;
-            }
-
-            if (pkgList != null && (pkgList.length > 0) && !removingPackage) {
-                for (String pkgName : pkgList) {
-                    if (mRankerServicePackageName.equals(pkgName)) {
-                        registerRanker();
-                    }
-                }
-            }
-        }
-
-        protected void registerRanker() {
-            // Find the updatable ranker and register it.
-            if (mRankerServicePackageName == null) {
-                Slog.w(TAG, "could not start ranker service: no package specified!");
-                return;
-            }
-            Set<ComponentName> rankerComponents = queryPackageForServices(
-                    mRankerServicePackageName, UserHandle.USER_SYSTEM);
-            Iterator<ComponentName> iterator = rankerComponents.iterator();
-            if (iterator.hasNext()) {
-                ComponentName rankerComponent = iterator.next();
-                if (iterator.hasNext()) {
-                    Slog.e(TAG, "found multiple ranker services:" + rankerComponents);
-                } else {
-                    registerSystemService(rankerComponent, UserHandle.USER_SYSTEM);
-                }
-            } else {
-                Slog.w(TAG, "could not start ranker service: none found");
-            }
-        }
     }
 
     public class NotificationListeners extends ManagedServices {
@@ -4295,7 +4233,7 @@
                     mHandler.post(new Runnable() {
                         @Override
                         public void run() {
-                            notifyRemoved(info, oldSbnLightClone, update);
+                            notifyRemoved(info, oldSbnLightClone, update, REASON_USER_STOPPED);
                         }
                     });
                     continue;
@@ -4314,7 +4252,7 @@
         /**
          * asynchronously notify all listeners about a removed notification
          */
-        public void notifyRemovedLocked(StatusBarNotification sbn) {
+        public void notifyRemovedLocked(StatusBarNotification sbn, int reason) {
             // make a copy in case changes are made to the underlying Notification object
             // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
             // notification
@@ -4327,7 +4265,7 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        notifyRemoved(info, sbnLight, update);
+                        notifyRemoved(info, sbnLight, update, reason);
                     }
                 });
             }
@@ -4391,14 +4329,14 @@
         }
 
         private void notifyRemoved(ManagedServiceInfo info, StatusBarNotification sbn,
-                NotificationRankingUpdate rankingUpdate) {
+                NotificationRankingUpdate rankingUpdate, int reason) {
             if (!info.enabledAndUserMatches(sbn.getUserId())) {
                 return;
             }
             final INotificationListener listener = (INotificationListener) info.service;
             StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
             try {
-                listener.onNotificationRemoved(sbnHolder, rankingUpdate);
+                listener.onNotificationRemoved(sbnHolder, rankingUpdate, reason);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
             }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index a1256db..965257c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -101,11 +101,8 @@
     private String mUserExplanation;
     private String mPeopleExplanation;
 
-    private NotificationChannel mNotificationChannel;
-
     @VisibleForTesting
-    public NotificationRecord(Context context, StatusBarNotification sbn,
-            NotificationChannel channel)
+    public NotificationRecord(Context context, StatusBarNotification sbn)
     {
         this.sbn = sbn;
         mOriginalFlags = sbn.getNotification().flags;
@@ -114,7 +111,6 @@
         mUpdateTimeMs = mCreationTimeMs;
         mContext = context;
         stats = new NotificationUsageStats.SingleNotificationStats();
-        mNotificationChannel = channel;
         mImportance = defaultImportance();
     }
 
@@ -148,8 +144,8 @@
                 || (n.defaults & Notification.DEFAULT_VIBRATE) != 0
                 || n.sound != null
                 || n.vibrate != null
-                || mNotificationChannel.shouldVibrate()
-                || mNotificationChannel.getRingtone() != null;
+                || sbn.getNotificationChannel().shouldVibrate()
+                || sbn.getNotificationChannel().getRingtone() != null;
         stats.isNoisy = isNoisy;
 
         if (!isNoisy && importance > IMPORTANCE_LOW) {
@@ -287,7 +283,7 @@
         pw.println(prefix + "  mVisibleSinceMs=" + mVisibleSinceMs);
         pw.println(prefix + "  mUpdateTimeMs=" + mUpdateTimeMs);
         pw.println(prefix + "  mSuppressedVisualEffects= " + mSuppressedVisualEffects);
-        pw.println(prefix + "  mNotificationChannel= " + mNotificationChannel);
+        pw.println(prefix + "  notificationChannel= " + notification.getNotificationChannel());
     }
 
 
@@ -535,6 +531,6 @@
     }
 
     public NotificationChannel getChannel() {
-        return mNotificationChannel;
+        return sbn.getNotificationChannel();
     }
 }
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index a6a3774..ecc03d7 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -32,7 +32,10 @@
 import android.os.UserHandle;
 import android.util.TimedRemoteCaller;
 
+import com.android.internal.os.TransferPipe;
+
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -51,6 +54,8 @@
     private final Object mLock = new Object();
     private final GetEphemeralResolveInfoCaller mGetEphemeralResolveInfoCaller =
             new GetEphemeralResolveInfoCaller();
+    private final GetEphemeralIntentFilterCaller mGetEphemeralIntentFilterCaller =
+            new GetEphemeralIntentFilterCaller();
     private final ServiceConnection mServiceConnection = new MyServiceConnection();
     private final Context mContext;
     /** Intent used to bind to the service */
@@ -64,12 +69,26 @@
         mIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE).setComponent(componentName);
     }
 
-    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(
-            int hashPrefix[], int prefixMask) {
+    public final List<EphemeralResolveInfo> getEphemeralResolveInfoList(int hashPrefix[]) {
         throwIfCalledOnMainThread();
         try {
             return mGetEphemeralResolveInfoCaller.getEphemeralResolveInfoList(
-                    getRemoteInstanceLazy(), hashPrefix, prefixMask);
+                    getRemoteInstanceLazy(), hashPrefix);
+        } catch (RemoteException re) {
+        } catch (TimeoutException te) {
+        } finally {
+            synchronized (mLock) {
+                mLock.notifyAll();
+            }
+        }
+        return null;
+    }
+
+    public final List<EphemeralResolveInfo> getEphemeralIntentFilterList(int digestPrefix[]) {
+        throwIfCalledOnMainThread();
+        try {
+            return mGetEphemeralIntentFilterCaller.getEphemeralIntentFilterList(
+                    getRemoteInstanceLazy(), digestPrefix);
         } catch (RemoteException re) {
         } catch (TimeoutException te) {
         } finally {
@@ -86,13 +105,11 @@
                     .append((mRemoteInstance != null) ? "true" : "false").println();
 
             pw.flush();
-
             try {
-                getRemoteInstanceLazy().asBinder().dump(fd, new String[] { prefix });
-            } catch (TimeoutException te) {
-                /* ignore */
-            } catch (RemoteException re) {
-                /* ignore */
+                TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd,
+                        new String[] { prefix });
+            } catch (IOException | TimeoutException | RemoteException e) {
+                pw.println("Failed to dump remote instance: " + e);
             }
         }
     }
@@ -181,10 +198,38 @@
         }
 
         public List<EphemeralResolveInfo> getEphemeralResolveInfoList(
-                IEphemeralResolver target, int hashPrefix[], int prefixMask)
+                IEphemeralResolver target, int hashPrefix[])
                         throws RemoteException, TimeoutException {
             final int sequence = onBeforeRemoteCall();
-            target.getEphemeralResolveInfoList(mCallback, hashPrefix, prefixMask, sequence);
+            target.getEphemeralResolveInfoList(mCallback, hashPrefix, sequence);
+            return getResultTimed(sequence);
+        }
+    }
+
+    private static final class GetEphemeralIntentFilterCaller
+            extends TimedRemoteCaller<List<EphemeralResolveInfo>> {
+        private final IRemoteCallback mCallback;
+
+        public GetEphemeralIntentFilterCaller() {
+            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
+            mCallback = new IRemoteCallback.Stub() {
+                @Override
+                public void sendResult(Bundle data) throws RemoteException {
+                    final ArrayList<EphemeralResolveInfo> resolveList =
+                            data.getParcelableArrayList(
+                                    EphemeralResolverService.EXTRA_RESOLVE_INFO);
+                    int sequence =
+                            data.getInt(EphemeralResolverService.EXTRA_SEQUENCE, -1);
+                    onRemoteMethodResult(resolveList, sequence);
+                }
+            };
+        }
+
+        public List<EphemeralResolveInfo> getEphemeralIntentFilterList(
+                IEphemeralResolver target, int digestPrefix[])
+                        throws RemoteException, TimeoutException {
+            final int sequence = onBeforeRemoteCall();
+            target.getEphemeralIntentFilterList(mCallback, digestPrefix, sequence);
             return getResultTimed(sequence);
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b1f2a24..79ef486 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -122,6 +122,7 @@
 import android.content.pm.AppsQueryHelper;
 import android.content.pm.ComponentInfo;
 import android.content.pm.EphemeralApplicationInfo;
+import android.content.pm.EphemeralIntentFilter;
 import android.content.pm.EphemeralResolveInfo;
 import android.content.pm.EphemeralResolveInfo.EphemeralDigest;
 import android.content.pm.EphemeralResolveInfo.EphemeralResolveIntentInfo;
@@ -478,9 +479,6 @@
     private static final String VENDOR_OVERLAY_THEME_PERSIST_PROPERTY
             = "persist.vendor.overlay.theme";
 
-    private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFF000;
-    private static int DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT = 5;
-
     /** Permission grant: not grant the permission. */
     private static final int GRANT_DENIED = 1;
 
@@ -1085,8 +1083,8 @@
     class DefaultContainerConnection implements ServiceConnection {
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
-            IMediaContainerService imcs =
-                IMediaContainerService.Stub.asInterface(service);
+            final IMediaContainerService imcs = IMediaContainerService.Stub
+                    .asInterface(Binder.allowBlocking(service));
             mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
         }
 
@@ -4945,19 +4943,15 @@
         return true;
     }
 
-    private static EphemeralResolveInfo getEphemeralResolveInfo(
+    private static EphemeralResolveIntentInfo getEphemeralIntentInfo(
             Context context, EphemeralResolverConnection resolverConnection, Intent intent,
             String resolvedType, int userId, String packageName) {
-        final int ephemeralPrefixMask = Global.getInt(context.getContentResolver(),
-                Global.EPHEMERAL_HASH_PREFIX_MASK, DEFAULT_EPHEMERAL_HASH_PREFIX_MASK);
-        final int ephemeralPrefixCount = Global.getInt(context.getContentResolver(),
-                Global.EPHEMERAL_HASH_PREFIX_COUNT, DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT);
-        final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixMask,
-                ephemeralPrefixCount);
+        final EphemeralDigest digest =
+                new EphemeralDigest(intent.getData().getHost(), 5 /*maxDigests*/);
         final int[] shaPrefix = digest.getDigestPrefix();
         final byte[][] digestBytes = digest.getDigestBytes();
         final List<EphemeralResolveInfo> ephemeralResolveInfoList =
-                resolverConnection.getEphemeralResolveInfoList(shaPrefix, ephemeralPrefixMask);
+                resolverConnection.getEphemeralResolveInfoList(shaPrefix);
         if (ephemeralResolveInfoList == null || ephemeralResolveInfoList.size() == 0) {
             // No hash prefix match; there are no ephemeral apps for this domain.
             return null;
@@ -4969,9 +4963,10 @@
                 if (!Arrays.equals(digestBytes[i], ephemeralApplication.getDigestBytes())) {
                     continue;
                 }
-                final List<IntentFilter> filters = ephemeralApplication.getFilters();
+                final List<EphemeralIntentFilter> ephemeralFilters =
+                        ephemeralApplication.getIntentFilters();
                 // No filters; this should never happen.
-                if (filters.isEmpty()) {
+                if (ephemeralFilters.isEmpty()) {
                     continue;
                 }
                 if (packageName != null
@@ -4980,13 +4975,21 @@
                 }
                 // We have a domain match; resolve the filters to see if anything matches.
                 final EphemeralIntentResolver ephemeralResolver = new EphemeralIntentResolver();
-                for (int j = filters.size() - 1; j >= 0; --j) {
-                    final EphemeralResolveIntentInfo intentInfo =
-                            new EphemeralResolveIntentInfo(filters.get(j), ephemeralApplication);
-                    ephemeralResolver.addFilter(intentInfo);
+                for (int j = ephemeralFilters.size() - 1; j >= 0; --j) {
+                    final EphemeralIntentFilter ephemeralFilter = ephemeralFilters.get(j);
+                    final List<IntentFilter> splitFilters = ephemeralFilter.getFilters();
+                    if (splitFilters == null || splitFilters.isEmpty()) {
+                        continue;
+                    }
+                    for (int k = splitFilters.size() - 1; k >= 0; --k) {
+                        final EphemeralResolveIntentInfo intentInfo =
+                                new EphemeralResolveIntentInfo(splitFilters.get(k),
+                                        ephemeralApplication, ephemeralFilter.getSplitName());
+                        ephemeralResolver.addFilter(intentInfo);
+                    }
                 }
-                List<EphemeralResolveInfo> matchedResolveInfoList = ephemeralResolver.queryIntent(
-                        intent, resolvedType, false /*defaultOnly*/, userId);
+                List<EphemeralResolveIntentInfo> matchedResolveInfoList = ephemeralResolver
+                        .queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
                 if (!matchedResolveInfoList.isEmpty()) {
                     return matchedResolveInfoList.get(0);
                 }
@@ -5469,15 +5472,15 @@
         }
         if (addEphemeral) {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
-            final EphemeralResolveInfo ai = getEphemeralResolveInfo(
+            final EphemeralResolveIntentInfo intentInfo = getEphemeralIntentInfo(
                     mContext, mEphemeralResolverConnection, intent, resolvedType, userId,
                     matchEphemeralPackage ? pkgName : null);
-            if (ai != null) {
+            if (intentInfo != null) {
                 if (DEBUG_EPHEMERAL) {
                     Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
                 }
                 final ResolveInfo ephemeralInstaller = new ResolveInfo(mEphemeralInstallerInfo);
-                ephemeralInstaller.ephemeralResolveInfo = ai;
+                ephemeralInstaller.ephemeralIntentInfo = intentInfo;
                 // make sure this resolver is the default
                 ephemeralInstaller.isDefault = true;
                 ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
@@ -11451,7 +11454,7 @@
     }
 
     private static final class EphemeralIntentResolver
-            extends IntentResolver<EphemeralResolveIntentInfo, EphemeralResolveInfo> {
+            extends IntentResolver<EphemeralResolveIntentInfo, EphemeralResolveIntentInfo> {
         /**
          * The result that has the highest defined order. Ordering applies on a
          * per-package basis. Mapping is from package name to Pair of order and
@@ -11476,7 +11479,7 @@
         }
 
         @Override
-        protected EphemeralResolveInfo newResult(EphemeralResolveIntentInfo info, int match,
+        protected EphemeralResolveIntentInfo newResult(EphemeralResolveIntentInfo info, int match,
                 int userId) {
             if (!sUserManager.exists(userId)) {
                 return null;
@@ -11494,18 +11497,18 @@
                 // non-zero order, enable ordering
                 mOrderResult.put(packageName, new Pair<>(order, res));
             }
-            return res;
+            return info;
         }
 
         @Override
-        protected void filterResults(List<EphemeralResolveInfo> results) {
+        protected void filterResults(List<EphemeralResolveIntentInfo> results) {
             // only do work if ordering is enabled [most of the time it won't be]
             if (mOrderResult.size() == 0) {
                 return;
             }
             int resultSize = results.size();
             for (int i = 0; i < resultSize; i++) {
-                final EphemeralResolveInfo info = results.get(i);
+                final EphemeralResolveInfo info = results.get(i).getEphemeralResolveInfo();
                 final String packageName = info.getPackageName();
                 final Pair<Integer, EphemeralResolveInfo> savedInfo = mOrderResult.get(packageName);
                 if (savedInfo == null) {
@@ -16624,7 +16627,8 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             synchronized (this) {
-                mContainerService = IMediaContainerService.Stub.asInterface(service);
+                mContainerService = IMediaContainerService.Stub
+                        .asInterface(Binder.allowBlocking(service));
                 notifyAll();
             }
         }
@@ -18097,8 +18101,10 @@
         }
 
         synchronized (mPackages) {
-            if (uid == Process.SHELL_UID) {
+            if (uid == Process.SHELL_UID
+                    && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
                 // Shell can only change whole packages between ENABLED and DISABLED_USER states
+                // unless it is a test package.
                 int oldState = pkgSetting.getEnabled(userId);
                 if (className == null
                     &&
@@ -21251,6 +21257,14 @@
         }
 
         @Override
+        public boolean isPackageEphemeral(int userId, String packageName) {
+            synchronized (mPackages) {
+                PackageParser.Package p = mPackages.get(packageName);
+                return p != null ? p.applicationInfo.isEphemeralApp() : false;
+            }
+        }
+
+        @Override
         public boolean wasPackageEverLaunched(String packageName, int userId) {
             synchronized (mPackages) {
                 return mSettings.wasPackageEverLaunchedLPr(packageName, userId);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ad31a32..5a0bee1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -467,7 +467,7 @@
         }
 
         @Override
-        public void onUidGone(int uid) throws RemoteException {
+        public void onUidGone(int uid, boolean disabled) throws RemoteException {
             handleOnUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
         }
 
@@ -476,7 +476,7 @@
         }
 
         @Override
-        public void onUidIdle(int uid) throws RemoteException {
+        public void onUidIdle(int uid, boolean disabled) throws RemoteException {
         }
     };
 
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index a8bd4d2..3bea663 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -19,7 +19,7 @@
 import com.android.internal.app.AlertController;
 import com.android.internal.app.AlertController.AlertParams;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.EmergencyAffordanceManager;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b7067d2..396c958 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -226,6 +226,7 @@
 import com.android.server.LocalServices;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
+import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.AppTransition;
 
@@ -6956,7 +6957,13 @@
     /** {@inheritDoc} */
     @Override
     public void systemReady() {
-        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
+        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
+                new StateCallback() {
+                    @Override
+                    public void onTrustedChanged() {
+                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
+                    }
+                });
         mKeyguardDelegate.onSystemReady();
 
         readCameraLensCoverState();
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 28f36f7..ca641fb 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,7 +1,5 @@
 package com.android.server.policy.keyguard;
 
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.content.ComponentName;
 import android.content.Context;
@@ -15,13 +13,11 @@
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
-import android.view.View;
 import android.view.WindowManagerPolicy.OnKeyguardExitResult;
 
 import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
-import com.android.server.LocalServices;
 import com.android.server.UiThread;
 
 import java.io.PrintWriter;
@@ -47,6 +43,8 @@
     private final Context mContext;
     private final Handler mHandler;
     private final KeyguardState mKeyguardState = new KeyguardState();
+    private final KeyguardStateMonitor.StateCallback mCallback;
+
     private DrawnListener mDrawnListenerWhenConnect;
 
     private static final class KeyguardState {
@@ -119,9 +117,10 @@
         }
     };
 
-    public KeyguardServiceDelegate(Context context) {
+    public KeyguardServiceDelegate(Context context, KeyguardStateMonitor.StateCallback callback) {
         mContext = context;
         mHandler = UiThread.getHandler();
+        mCallback = callback;
     }
 
     public void bindService(Context context) {
@@ -155,7 +154,7 @@
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
             mKeyguardService = new KeyguardServiceWrapper(mContext,
-                    IKeyguardService.Stub.asInterface(service));
+                    IKeyguardService.Stub.asInterface(service), mCallback);
             if (mKeyguardState.systemIsReady) {
                 // If the system is ready, it means keyguard crashed and restarted.
                 mKeyguardService.onSystemReady();
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index b457f8d..c4a0dd3 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -39,9 +39,10 @@
     private IKeyguardService mService;
     private String TAG = "KeyguardServiceWrapper";
 
-    public KeyguardServiceWrapper(Context context, IKeyguardService service) {
+    public KeyguardServiceWrapper(Context context, IKeyguardService service,
+            KeyguardStateMonitor.StateCallback callback) {
         mService = service;
-        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
+        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service, callback);
     }
 
     @Override // Binder interface
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index f19f0aa..941cd44 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -49,10 +49,12 @@
     private int mCurrentUserId;
 
     private final LockPatternUtils mLockPatternUtils;
+    private final StateCallback mCallback;
 
-    public KeyguardStateMonitor(Context context, IKeyguardService service) {
+    public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) {
         mLockPatternUtils = new LockPatternUtils(context);
         mCurrentUserId = ActivityManager.getCurrentUser();
+        mCallback = callback;
 
         try {
             service.addStateMonitorCallback(this);
@@ -107,6 +109,7 @@
     @Override // Binder interface
     public void onTrustedChanged(boolean trusted) {
         mTrusted = trusted;
+        mCallback.onTrustedChanged();
     }
 
     @Override // Binder interface
@@ -114,6 +117,10 @@
         mHasLockscreenWallpaper = hasLockscreenWallpaper;
     }
 
+    public interface StateCallback {
+        void onTrustedChanged();
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + TAG);
         prefix += "  ";
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
new file mode 100644
index 0000000..23be9a3
--- /dev/null
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.storage;
+
+import android.annotation.CallSuper;
+import android.annotation.WorkerThread;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.util.Log;
+import com.android.internal.os.AppFuseMount;
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+public class AppFuseBridge implements Runnable {
+    private static final String TAG = AppFuseBridge.class.getSimpleName();
+
+    private final FileDescriptor mDeviceFd;
+    private final FileDescriptor mProxyFd;
+    private final CountDownLatch mMountLatch = new CountDownLatch(1);
+
+    /**
+     * @param deviceFd FD of /dev/fuse. Ownership of fd is taken by AppFuseBridge.
+     * @param proxyFd FD of socket pair. Ownership of fd is taken by AppFuseBridge.
+     */
+    private AppFuseBridge(FileDescriptor deviceFd, FileDescriptor proxyFd) {
+        mDeviceFd = deviceFd;
+        mProxyFd = proxyFd;
+    }
+
+    public static AppFuseMount startMessageLoop(
+            int uid,
+            String name,
+            FileDescriptor deviceFd,
+            Handler handler,
+            ParcelFileDescriptor.OnCloseListener listener)
+                    throws IOException, ErrnoException, InterruptedException {
+        final FileDescriptor localFd = new FileDescriptor();
+        final FileDescriptor remoteFd = new FileDescriptor();
+        // Needs to specify OsConstants.SOCK_SEQPACKET to keep message boundaries.
+        Os.socketpair(OsConstants.AF_UNIX, OsConstants.SOCK_SEQPACKET, 0, remoteFd, localFd);
+
+        // Caller must invoke #start() after instantiate AppFuseBridge.
+        // Otherwise FDs will be leaked.
+        final AppFuseBridge bridge = new AppFuseBridge(deviceFd, localFd);
+        final Thread thread = new Thread(bridge, TAG);
+        thread.start();
+        try {
+            bridge.mMountLatch.await();
+        } catch (InterruptedException error) {
+            throw error;
+        }
+        return new AppFuseMount(
+                new File("/mnt/appfuse/" + uid + "_" + name),
+                ParcelFileDescriptor.fromFd(remoteFd, handler, listener));
+    }
+
+    @Override
+    public void run() {
+        // deviceFd and proxyFd must be closed in native_start_loop.
+        final int deviceFd = mDeviceFd.getInt$();
+        final int proxyFd = mProxyFd.getInt$();
+        mDeviceFd.setInt$(-1);
+        mProxyFd.setInt$(-1);
+        native_start_loop(deviceFd, proxyFd);
+    }
+
+    // Used by com_android_server_storage_AppFuse.cpp.
+    private void onMount() {
+        mMountLatch.countDown();
+    }
+
+    private native boolean native_start_loop(int deviceFd, int proxyFd);
+}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 622eece..05e6f96 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -66,6 +66,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 class AppTokenList extends ArrayList<AppWindowToken> {
 }
@@ -1269,6 +1270,22 @@
     }
 
     @Override
+    void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
+        // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
+        // before the non-exiting app tokens. So, we skip the exiting app tokens here.
+        // TODO: Investigate if we need to continue to do this or if we can just process them
+        // in-order.
+        if (mIsExiting && !waitingForReplacement()) {
+            return;
+        }
+        forAllWindowsUnchecked(callback, traverseTopToBottom);
+    }
+
+    void forAllWindowsUnchecked(Consumer<WindowState> callback, boolean traverseTopToBottom) {
+        super.forAllWindows(callback, traverseTopToBottom);
+    }
+
+    @Override
     AppWindowToken asAppWindowToken() {
         // I am an app window token!
         return this;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ec4cdf2..6a625f4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -140,6 +140,7 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -1121,8 +1122,7 @@
         for (int i = 0; i < windowCount; i++) {
             final WindowState window = mWindows.get(i);
             if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
-                    && !window.mPermanentlyHidden && !window.mAnimatingExit
-                    && !window.mRemoveOnExit) {
+                    && !window.mPermanentlyHidden && !window.mWindowRemovalAllowed) {
                 return false;
             }
         }
@@ -3243,6 +3243,42 @@
         }
 
         @Override
+        void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
+            if (traverseTopToBottom) {
+                super.forAllWindows(callback, traverseTopToBottom);
+                forAllExitingAppTokenWindows(callback, traverseTopToBottom);
+            } else {
+                forAllExitingAppTokenWindows(callback, traverseTopToBottom);
+                super.forAllWindows(callback, traverseTopToBottom);
+            }
+        }
+
+        private void forAllExitingAppTokenWindows(Consumer<WindowState> callback,
+                boolean traverseTopToBottom) {
+            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
+            // app tokens.
+            // TODO: Investigate if we need to continue to do this or if we can just process them
+            // in-order.
+            if (traverseTopToBottom) {
+                for (int i = mChildren.size() - 1; i >= 0; --i) {
+                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
+                    for (int j = appTokens.size() - 1; j >= 0; --j) {
+                        appTokens.get(j).forAllWindowsUnchecked(callback, traverseTopToBottom);
+                    }
+                }
+            } else {
+                final int count = mChildren.size();
+                for (int i = 0; i < count; ++i) {
+                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
+                    final int appTokensCount = appTokens.size();
+                    for (int j = 0; j < appTokensCount; j++) {
+                        appTokens.get(j).forAllWindowsUnchecked(callback, traverseTopToBottom);
+                    }
+                }
+            }
+        }
+
+        @Override
         int getOrientation() {
             if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
                     || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 52c18f1..effb1b2 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -44,6 +44,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.policy.PipMotionHelper;
 import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.server.UiThread;
 
 import java.io.PrintWriter;
 
@@ -56,7 +57,7 @@
 
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
-    private final Handler mHandler = new Handler();
+    private final Handler mHandler = UiThread.getHandler();
 
     private IPinnedStackListener mPinnedStackListener;
     private final PinnedStackListenerDeathHandler mPinnedStackListenerDeathHandler =
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f038135..299fa05 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -40,9 +40,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.OP_NONE;
@@ -55,17 +53,13 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -78,7 +72,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
@@ -760,9 +753,6 @@
                 WindowToken token = exitingTokens.get(i);
                 if (!token.hasVisible) {
                     exitingTokens.remove(i);
-                    if (token.windowType == TYPE_WALLPAPER) {
-                        displayContent.mWallpaperController.removeWallpaperToken(token);
-                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 250d381..178fbe7 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -55,7 +55,7 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperController" : TAG_WM;
     final private WindowManagerService mService;
 
-    private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<>();
+    private final ArrayList<WallpaperWindowToken> mWallpaperTokens = new ArrayList<>();
 
     // If non-null, this is the currently visible window that is associated
     // with the wallpaper.
@@ -135,7 +135,7 @@
      */
     void startWallpaperAnimation(Animation a) {
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             token.startAnimation(a);
         }
     }
@@ -163,7 +163,7 @@
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
 
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             token.updateWallpaperVisibility(visible);
         }
     }
@@ -189,7 +189,7 @@
 
         final boolean wasDeferred = (mDeferredHideWallpaper == winGoingAway);
         for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
-            final WindowToken token = mWallpaperTokens.get(i);
+            final WallpaperWindowToken token = mWallpaperTokens.get(i);
             token.hideWallpaperToken(wasDeferred, "hideWallpapers");
             if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
                     + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
@@ -304,7 +304,7 @@
                 || window == mUpperWallpaperTarget) {
             boolean doWait = sync;
             for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-                final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+                final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
                 token.sendWindowWallpaperCommand(action, x, y, z, extras, sync);
             }
 
@@ -652,7 +652,7 @@
         // Start stepping backwards from here, ensuring that our wallpaper windows are correctly placed.
         boolean changed = false;
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
             changed |= token.updateWallpaperWindowsPlacement(windows, wallpaperTarget,
                     wallpaperTargetIndex, visible, dw, dh, mWallpaperAnimLayerAdjustment);
         }
@@ -725,7 +725,7 @@
         boolean wallpaperReady = true;
         for (int curTokenIndex = mWallpaperTokens.size() - 1;
                 curTokenIndex >= 0 && wallpaperReady; curTokenIndex--) {
-            final WindowToken token = mWallpaperTokens.get(curTokenIndex);
+            final WallpaperWindowToken token = mWallpaperTokens.get(curTokenIndex);
             if (token.hasVisibleNotDrawnWallpaper()) {
                 // We've told this wallpaper to be visible, but it is not drawn yet
                 wallpaperReady = false;
@@ -777,11 +777,11 @@
         }
     }
 
-    void addWallpaperToken(WindowToken token) {
+    void addWallpaperToken(WallpaperWindowToken token) {
         mWallpaperTokens.add(token);
     }
 
-    void removeWallpaperToken(WindowToken token) {
+    void removeWallpaperToken(WallpaperWindowToken token) {
         mWallpaperTokens.remove(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
new file mode 100644
index 0000000..fdefcfe
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.animation.Animation;
+
+/**
+ * A token that represents a set of wallpaper windows.
+ */
+class WallpaperWindowToken extends WindowToken {
+
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "WallpaperWindowToken" : TAG_WM;
+
+    WallpaperWindowToken(WindowManagerService service, IBinder token, boolean explicit,
+            DisplayContent dc) {
+        super(service, token, TYPE_WALLPAPER, explicit, dc);
+        dc.mWallpaperController.addWallpaperToken(this);
+    }
+
+    @Override
+    void setExiting() {
+        super.setExiting();
+        mDisplayContent.mWallpaperController.removeWallpaperToken(this);
+    }
+
+    void hideWallpaperToken(boolean wasDeferred, String reason) {
+        for (int j = mChildren.size() - 1; j >= 0; j--) {
+            final WindowState wallpaper = mChildren.get(j);
+            wallpaper.hideWallpaperWindow(wasDeferred, reason);
+        }
+        hidden = true;
+    }
+
+    void sendWindowWallpaperCommand(
+            String action, int x, int y, int z, Bundle extras, boolean sync) {
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+            try {
+                wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
+                // We only want to be synchronous with one wallpaper.
+                sync = false;
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    void updateWallpaperOffset(int dw, int dh, boolean sync) {
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+            if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
+                final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+                winAnimator.computeShownFrameLocked();
+                // No need to lay out the windows - we can just set the wallpaper position directly.
+                winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
+                // We only want to be synchronous with one wallpaper.
+                sync = false;
+            }
+        }
+    }
+
+    void updateWallpaperVisibility(boolean visible) {
+        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+        final int dw = displayInfo.logicalWidth;
+        final int dh = displayInfo.logicalHeight;
+
+        if (hidden == visible) {
+            hidden = !visible;
+            // Need to do a layout to ensure the wallpaper now has the correct size.
+            mDisplayContent.setLayoutNeeded();
+        }
+
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+            if (visible) {
+                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
+            }
+
+            wallpaper.dispatchWallpaperVisibility(visible);
+        }
+    }
+
+    /**
+     * Starts {@param anim} on all children.
+     */
+    void startAnimation(Animation anim) {
+        for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
+            final WindowState windowState = mChildren.get(ndx);
+            windowState.mWinAnimator.setAnimation(anim);
+        }
+    }
+
+    boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList,
+            WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh,
+            int wallpaperAnimLayerAdj) {
+
+        boolean changed = false;
+        if (hidden == visible) {
+            if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
+                    "Wallpaper token " + token + " hidden=" + !visible);
+            hidden = !visible;
+            // Need to do a layout to ensure the wallpaper now has the correct size.
+            mDisplayContent.setLayoutNeeded();
+        }
+
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = mChildren.get(wallpaperNdx);
+
+            if (visible) {
+                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
+            }
+
+            // First, make sure the client has the current visibility state.
+            wallpaper.dispatchWallpaperVisibility(visible);
+            wallpaper.adjustAnimLayer(wallpaperAnimLayerAdj);
+
+            if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
+                    + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
+
+            // First, if this window is at the current index, then all is well.
+            if (wallpaper == wallpaperTarget) {
+                wallpaperTargetIndex--;
+                wallpaperTarget = wallpaperTargetIndex > 0
+                        ? windowList.get(wallpaperTargetIndex - 1) : null;
+                continue;
+            }
+
+            // The window didn't match...  the current wallpaper window,
+            // wherever it is, is in the wrong place, so make sure it is not in the list.
+            int oldIndex = windowList.indexOf(wallpaper);
+            if (oldIndex >= 0) {
+                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
+                        "Wallpaper removing at " + oldIndex + ": " + wallpaper);
+                mDisplayContent.removeFromWindowList(wallpaper);
+                if (oldIndex < wallpaperTargetIndex) {
+                    wallpaperTargetIndex--;
+                }
+            }
+
+            // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
+            // layer. For keyguard over wallpaper put the wallpaper under the lowest window that
+            // is currently on screen, i.e. not hidden by policy.
+            int insertionIndex = 0;
+            if (visible && wallpaperTarget != null) {
+                final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
+                if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                    insertionIndex = Math.min(windowList.indexOf(wallpaperTarget),
+                            findLowestWindowOnScreen(windowList));
+                }
+            }
+            if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT
+                    || (DEBUG_ADD_REMOVE && oldIndex != insertionIndex)) Slog.v(TAG,
+                    "Moving wallpaper " + wallpaper + " from " + oldIndex + " to " + insertionIndex);
+
+            mDisplayContent.addToWindowList(wallpaper, insertionIndex);
+            changed = true;
+        }
+
+        return changed;
+    }
+
+    /**
+     * @return The index in {@param windows} of the lowest window that is currently on screen and
+     *         not hidden by the policy.
+     */
+    private int findLowestWindowOnScreen(ReadOnlyWindowList windowList) {
+        final int size = windowList.size();
+        for (int index = 0; index < size; index++) {
+            final WindowState win = windowList.get(index);
+            if (win.isOnScreen()) {
+                return index;
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    boolean hasVisibleNotDrawnWallpaper() {
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState wallpaper = mChildren.get(j);
+            if (wallpaper.hasVisibleNotDrawnWallpaper()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        if (stringName == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("WallpaperWindowToken{");
+            sb.append(Integer.toHexString(System.identityHashCode(this)));
+            sb.append(" token="); sb.append(token); sb.append('}');
+            stringName = sb.toString();
+        }
+        return stringName;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index e30ebcb..62ad217 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -22,6 +22,7 @@
 
 import java.util.Comparator;
 import java.util.LinkedList;
+import java.util.function.Consumer;
 
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -494,6 +495,19 @@
         return addIndex;
     }
 
+    void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                mChildren.get(i).forAllWindows(callback, traverseTopToBottom);
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; i++) {
+                mChildren.get(i).forAllWindows(callback, traverseTopToBottom);
+            }
+        }
+    }
+
     /**
      * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
      * the input container in terms of z-order.
@@ -562,8 +576,7 @@
     void dumpChildrenNames(StringBuilder out, String prefix) {
         final String childPrefix = prefix + " ";
         out.append(getName() + "\n");
-        final int count = mChildren.size();
-        for (int i = 0; i < count; i++) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowContainer wc = mChildren.get(i);
             out.append(childPrefix + "#" + i + " ");
             wc.dumpChildrenNames(out, childPrefix);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8be87a1..5c9dc10 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2414,9 +2414,10 @@
                         + " displayId=" + displayId);
                 return;
             }
-            token = new WindowToken(this, binder, type, true, dc);
             if (type == TYPE_WALLPAPER) {
-                dc.mWallpaperController.addWallpaperToken(token);
+                new WallpaperWindowToken(this, binder, true, dc);
+            } else {
+                new WindowToken(this, binder, type, true, dc);
             }
         }
     }
@@ -2445,9 +2446,6 @@
                 }
 
                 token.setExiting();
-                if (token.windowType == TYPE_WALLPAPER) {
-                    dc.mWallpaperController.removeWallpaperToken(token);
-                }
 
                 mInputMonitor.updateInputWindowsLw(true /*force*/);
             }
@@ -3618,6 +3616,11 @@
         notifyKeyguardFlagsChanged(null /* callback */);
     }
 
+    @Override
+    public void notifyKeyguardTrustedChanged() {
+        mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
+    }
+
     /**
      * Re-sizes a stack and its containing tasks.
      * @param stackId Id of stack to resize.
@@ -6156,6 +6159,7 @@
         public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
         public static final int RESTORE_POINTER_ICON = 55;
         public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
+        public static final int NOTIFY_KEYGUARD_TRUSTED_CHANGED = 57;
 
         /**
          * Used to denote that an integer field in a message will not be used.
@@ -6794,6 +6798,11 @@
                 case NOTIFY_KEYGUARD_FLAGS_CHANGED: {
                     mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj);
                 }
+                break;
+                case NOTIFY_KEYGUARD_TRUSTED_CHANGED: {
+                    mAmInternal.notifyKeyguardTrustedChanged();
+                }
+                break;
             }
             if (DEBUG_WINDOW_TRACE) {
                 Slog.v(TAG_WM, "handleMessage: exit");
@@ -8243,6 +8252,8 @@
                     StringBuilder output = new StringBuilder();
                     mRoot.dumpChildrenNames(output, " ");
                     pw.println(output.toString());
+                    pw.println(" ");
+                    mRoot.forAllWindows(pw::println, true /* traverseTopToBottom */);
                 }
                 return;
             } else {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 972c359..1a56518 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -59,6 +59,7 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedList;
+import java.util.function.Consumer;
 
 import static android.app.ActivityManager.StackId;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -488,7 +489,7 @@
      * or some other higher level component said so (e.g. activity manager).
      * TODO: We should either have different booleans for the removal reason or use a bit-field.
      */
-    private boolean mWindowRemovalAllowed;
+    boolean mWindowRemovalAllowed;
 
     /**
      * Temp for keeping track of windows that have been removed when
@@ -3876,6 +3877,78 @@
         return index;
     }
 
+    @Override
+    void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
+        if (mChildren.isEmpty()) {
+            // The window has no children so we just return it.
+            callback.accept(this);
+            return;
+        }
+
+        if (traverseTopToBottom) {
+            forAllWindowTopToBottom(callback);
+        } else {
+            forAllWindowBottomToTop(callback);
+        }
+    }
+
+    private void forAllWindowBottomToTop(Consumer<WindowState> callback) {
+        // We want to consumer the negative sublayer children first because they need to appear
+        // below the parent, then this window (the parent), and then the positive sublayer children
+        // because they need to appear above the parent.
+        int i = 0;
+        final int count = mChildren.size();
+        WindowState child = mChildren.get(i);
+
+        while (i < count && child.mSubLayer < 0) {
+            callback.accept(child);
+            i++;
+            if (i >= count) {
+                break;
+            }
+            child = mChildren.get(i);
+        }
+
+        callback.accept(this);
+
+        while (i < count) {
+            callback.accept(child);
+            i++;
+            if (i >= count) {
+                break;
+            }
+            child = mChildren.get(i);
+        }
+    }
+
+    private void forAllWindowTopToBottom(Consumer<WindowState> callback) {
+        // We want to consumer the positive sublayer children first because they need to appear
+        // above the parent, then this window (the parent), and then the negative sublayer children
+        // because they need to appear above the parent.
+        int i = mChildren.size() - 1;
+        WindowState child = mChildren.get(i);
+
+        while (i >= 0 && child.mSubLayer >= 0) {
+            callback.accept(child);
+            --i;
+            if (i < 0) {
+                break;
+            }
+            child = mChildren.get(i);
+        }
+
+        callback.accept(this);
+
+        while (i >= 0) {
+            callback.accept(child);
+            --i;
+            if (i < 0) {
+                break;
+            }
+            child = mChildren.get(i);
+        }
+    }
+
     boolean isWindowAnimationSet() {
         if (mWinAnimator.isWindowAnimationSet()) {
             return true;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index b821f09..402bcfb 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -82,7 +82,7 @@
     boolean sendingToBottom;
 
     // The display this token is on.
-    private DisplayContent mDisplayContent;
+    protected DisplayContent mDisplayContent;
 
     /**
      * Compares two child window of this token and returns -1 if the first is lesser than the
@@ -196,9 +196,8 @@
      */
     protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
             WindowState existingWindow) {
-        // By default the first window isn't greater than the second to preserve existing logic of
-        // how new windows are added to the token
-        return false;
+        // New window is considered greater if it has a higher or equal base layer.
+        return newWindow.mBaseLayer >= existingWindow.mBaseLayer;
     }
 
     void addWindow(final WindowState win) {
@@ -280,169 +279,6 @@
         return false;
     }
 
-    void hideWallpaperToken(boolean wasDeferred, String reason) {
-        for (int j = mChildren.size() - 1; j >= 0; j--) {
-            final WindowState wallpaper = mChildren.get(j);
-            wallpaper.hideWallpaperWindow(wasDeferred, reason);
-        }
-        hidden = true;
-    }
-
-    void sendWindowWallpaperCommand(
-            String action, int x, int y, int z, Bundle extras, boolean sync) {
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            try {
-                wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
-                // We only want to be synchronous with one wallpaper.
-                sync = false;
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    void updateWallpaperOffset(int dw, int dh, boolean sync) {
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
-                final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
-                winAnimator.computeShownFrameLocked();
-                // No need to lay out the windows - we can just set the wallpaper position directly.
-                winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
-                // We only want to be synchronous with one wallpaper.
-                sync = false;
-            }
-        }
-    }
-
-    void updateWallpaperVisibility(boolean visible) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-        final int dw = displayInfo.logicalWidth;
-        final int dh = displayInfo.logicalHeight;
-
-        if (hidden == visible) {
-            hidden = !visible;
-            // Need to do a layout to ensure the wallpaper now has the correct size.
-            mDisplayContent.setLayoutNeeded();
-        }
-
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-            if (visible) {
-                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
-            }
-
-            wallpaper.dispatchWallpaperVisibility(visible);
-        }
-    }
-
-    /**
-     * Starts {@param anim} on all children.
-     */
-    void startAnimation(Animation anim) {
-        for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
-            final WindowState windowState = mChildren.get(ndx);
-            windowState.mWinAnimator.setAnimation(anim);
-        }
-    }
-
-    boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList,
-            WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh,
-            int wallpaperAnimLayerAdj) {
-
-        boolean changed = false;
-        if (hidden == visible) {
-            if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
-                    "Wallpaper token " + token + " hidden=" + !visible);
-            hidden = !visible;
-            // Need to do a layout to ensure the wallpaper now has the correct size.
-            mDisplayContent.setLayoutNeeded();
-        }
-
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
-        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = mChildren.get(wallpaperNdx);
-
-            if (visible) {
-                wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
-            }
-
-            // First, make sure the client has the current visibility state.
-            wallpaper.dispatchWallpaperVisibility(visible);
-            wallpaper.adjustAnimLayer(wallpaperAnimLayerAdj);
-
-            if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
-                    + wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
-
-            // First, if this window is at the current index, then all is well.
-            if (wallpaper == wallpaperTarget) {
-                wallpaperTargetIndex--;
-                wallpaperTarget = wallpaperTargetIndex > 0
-                        ? windowList.get(wallpaperTargetIndex - 1) : null;
-                continue;
-            }
-
-            // The window didn't match...  the current wallpaper window,
-            // wherever it is, is in the wrong place, so make sure it is not in the list.
-            int oldIndex = windowList.indexOf(wallpaper);
-            if (oldIndex >= 0) {
-                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
-                        "Wallpaper removing at " + oldIndex + ": " + wallpaper);
-                mDisplayContent.removeFromWindowList(wallpaper);
-                if (oldIndex < wallpaperTargetIndex) {
-                    wallpaperTargetIndex--;
-                }
-            }
-
-            // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
-            // layer. For keyguard over wallpaper put the wallpaper under the lowest window that
-            // is currently on screen, i.e. not hidden by policy.
-            int insertionIndex = 0;
-            if (visible && wallpaperTarget != null) {
-                final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
-                if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                    insertionIndex = Math.min(windowList.indexOf(wallpaperTarget),
-                            findLowestWindowOnScreen(windowList));
-                }
-            }
-            if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT
-                    || (DEBUG_ADD_REMOVE && oldIndex != insertionIndex)) Slog.v(TAG,
-                    "Moving wallpaper " + wallpaper + " from " + oldIndex + " to " + insertionIndex);
-
-            mDisplayContent.addToWindowList(wallpaper, insertionIndex);
-            changed = true;
-        }
-
-        return changed;
-    }
-
-    /**
-     * @return The index in {@param windows} of the lowest window that is currently on screen and
-     *         not hidden by the policy.
-     */
-    private int findLowestWindowOnScreen(ReadOnlyWindowList windowList) {
-        final int size = windowList.size();
-        for (int index = 0; index < size; index++) {
-            final WindowState win = windowList.get(index);
-            if (win.isOnScreen()) {
-                return index;
-            }
-        }
-        return Integer.MAX_VALUE;
-    }
-
-    boolean hasVisibleNotDrawnWallpaper() {
-        for (int j = mChildren.size() - 1; j >= 0; --j) {
-            final WindowState wallpaper = mChildren.get(j);
-            if (wallpaper.hasVisibleNotDrawnWallpaper()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     int getHighestAnimLayer() {
         int highest = -1;
         for (int j = 0; j < mChildren.size(); j++) {
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index a4b5e6a..c03a460 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -19,6 +19,7 @@
     $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \
     $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_storage_AppFuseBridge.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SystemServer.cpp \
     $(LOCAL_REL_DIR)/com_android_server_tv_TvUinputBridge.cpp \
     $(LOCAL_REL_DIR)/com_android_server_tv_TvInputHal.cpp \
@@ -37,6 +38,7 @@
     frameworks/base/libs/hwui \
     frameworks/base/core/jni \
     frameworks/native/services \
+    system/core/libappfuse/include \
     system/security/keystore/include \
     $(call include-path-for, libhardware)/hardware \
     $(call include-path-for, libhardware_legacy)/hardware_legacy \
@@ -44,6 +46,7 @@
 LOCAL_SHARED_LIBRARIES += \
     libandroid_runtime \
     libandroidfw \
+    libappfuse \
     libbinder \
     libcutils \
     liblog \
diff --git a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
new file mode 100644
index 0000000..640fd0e
--- /dev/null
+++ b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 specic language governing permissions and
+ * limitations under the License.
+ */
+
+// Need to use LOGE_EX.
+#define LOG_TAG "AppFuseBridge"
+
+#include <android_runtime/Log.h>
+#include <android-base/logging.h>
+#include <core_jni_helpers.h>
+#include <libappfuse/FuseBridgeLoop.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+namespace {
+
+constexpr const char* CLASS_NAME = "com/android/server/storage/AppFuseBridge";
+static jclass appFuseClass;
+static jmethodID appFuseOnMount;
+
+class Callback : public FuseBridgeLoop::Callback {
+    JNIEnv* mEnv;
+    jobject mSelf;
+
+public:
+    Callback(JNIEnv* env, jobject self) : mEnv(env), mSelf(self) {}
+    void OnMount() override {
+        mEnv->CallVoidMethod(mSelf, appFuseOnMount);
+        if (mEnv->ExceptionCheck()) {
+            LOGE_EX(mEnv, nullptr);
+            mEnv->ExceptionClear();
+        }
+    }
+};
+
+jboolean com_android_server_storage_AppFuseBridge_start_loop(
+        JNIEnv* env, jobject self, jint devJavaFd, jint proxyJavaFd) {
+    FuseBridgeLoop loop;
+    Callback callback(env, self);
+    return loop.Start(devJavaFd, proxyJavaFd, &callback);
+}
+
+const JNINativeMethod methods[] = {
+    {
+        "native_start_loop",
+        "(II)Z",
+        (void *) com_android_server_storage_AppFuseBridge_start_loop
+    }
+};
+
+}  // namespace
+
+void register_android_server_storage_AppFuse(JNIEnv* env) {
+    CHECK(env != nullptr);
+
+    appFuseClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, CLASS_NAME));
+    appFuseOnMount = GetMethodIDOrDie(env, appFuseClass, "onMount", "()V");
+    RegisterMethodsOrDie(env, CLASS_NAME, methods, NELEM(methods));
+}
+}  // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index d69c37f..c291ba0 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -28,6 +28,7 @@
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
 int register_android_server_PowerManagerService(JNIEnv* env);
+int register_android_server_storage_AppFuse(JNIEnv* env);
 int register_android_server_SerialService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
 int register_android_server_UsbDeviceManager(JNIEnv* env);
@@ -83,6 +84,7 @@
     register_android_server_PersistentDataBlockService(env);
     register_android_server_Watchdog(env);
     register_android_server_HardwarePropertiesManagerService(env);
+    register_android_server_storage_AppFuse(env);
 
     return JNI_VERSION_1_4;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0ea8d4e..7f8b9b8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -22,7 +22,7 @@
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
 
-import static com.android.internal.logging.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cc96f56..3db24fa 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -27,6 +27,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources.Theme;
 import android.os.BaseBundle;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
@@ -184,6 +185,8 @@
             "com.android.server.content.ContentService$Lifecycle";
     private static final String WALLPAPER_SERVICE_CLASS =
             "com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
+    private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
+            "com.android.server.autofill.AutoFillManagerService";
 
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
@@ -267,6 +270,9 @@
                 SystemProperties.set("persist.sys.localevar", "");
             }
 
+            // The system server should never make non-oneway calls
+            Binder.setWarnOnBlocking(true);
+
             // Here we go!
             Slog.i(TAG, "Entered the Android system server!");
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
@@ -1362,6 +1368,10 @@
         mSystemServiceManager.startService(RetailDemoModeService.class);
         traceEnd();
 
+        traceBeginAndSlog("StartAutoFillService");
+        mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
+        traceEnd();
+
         // It is now time to start up the app processes...
 
         traceBeginAndSlog("MakeVibratorServiceReady");
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 01d9304..39f14e5 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -631,6 +631,11 @@
         return shouldLog;
     }
 
+    // TODO: Migrate all Log.e(...) to logError(...).
+    private void logError(String fmt, Object... args) {
+        mLocalLog.log("ERROR " + String.format(fmt, args));
+    }
+
     private void getNetworkInterface() {
         try {
             mNetworkInterface = NetworkInterface.getByName(mInterfaceName);
@@ -880,7 +885,7 @@
             mNwService.setInterfaceConfig(mInterfaceName, ifcg);
             if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");
         } catch (IllegalStateException | RemoteException e) {
-            Log.e(mTag, "IPv4 configuration failed: ", e);
+            logError("IPv4 configuration failed: %s", e);
             return false;
         }
         return true;
@@ -944,6 +949,12 @@
         }
     }
 
+    private void doImmediateProvisioningFailure(int failureType) {
+        if (DBG) { Log.e(mTag, "onProvisioningFailure(): " + failureType); }
+        recordMetric(failureType);
+        mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties));
+    }
+
     private boolean startIPv4() {
         // If we have a StaticIpConfiguration attempt to apply it and
         // handle the result accordingly.
@@ -951,9 +962,6 @@
             if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
                 handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
             } else {
-                if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
-                recordMetric(IpManagerEvent.PROVISIONING_FAIL);
-                mCallback.onProvisioningFailure(new LinkProperties(mLinkProperties));
                 return false;
             }
         } else {
@@ -972,16 +980,40 @@
             mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
             mNwService.enableIpv6(mInterfaceName);
         } catch (RemoteException re) {
-            Log.e(mTag, "Unable to change interface settings: " + re);
+            logError("Unable to change interface settings: %s", re);
             return false;
         } catch (IllegalStateException ie) {
-            Log.e(mTag, "Unable to change interface settings: " + ie);
+            logError("Unable to change interface settings: %s", ie);
             return false;
         }
 
         return true;
     }
 
+    private boolean startIpReachabilityMonitor() {
+        try {
+            mIpReachabilityMonitor = new IpReachabilityMonitor(
+                    mContext,
+                    mInterfaceName,
+                    new IpReachabilityMonitor.Callback() {
+                        @Override
+                        public void notifyLost(InetAddress ip, String logMsg) {
+                            mCallback.onReachabilityLost(logMsg);
+                        }
+                    },
+                    mAvoidBadWifiTracker);
+        } catch (IllegalArgumentException iae) {
+            // Failed to start IpReachabilityMonitor. Log it and call
+            // onProvisioningFailure() immediately.
+            //
+            // See http://b/31038971.
+            logError("IpReachabilityMonitor failure: %s", iae);
+            mIpReachabilityMonitor = null;
+        }
+
+        return (mIpReachabilityMonitor != null);
+    }
+
     private void stopAllIP() {
         // We don't need to worry about routes, just addresses, because:
         //     - disableIpv6() will clear autoconf IPv6 routes as well, and
@@ -1165,29 +1197,23 @@
                 mCallback.setFallbackMulticastFilter(mMulticastFiltering);
             }
 
-            if (mConfiguration.mEnableIPv6) {
-                // TODO: Consider transitionTo(mStoppingState) if this fails.
-                startIPv6();
+            if (mConfiguration.mEnableIPv6 && !startIPv6()) {
+                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
+                transitionTo(mStoppingState);
+                return;
             }
 
-            if (mConfiguration.mEnableIPv4) {
-                if (!startIPv4()) {
-                    transitionTo(mStoppingState);
-                    return;
-                }
+            if (mConfiguration.mEnableIPv4 && !startIPv4()) {
+                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
+                transitionTo(mStoppingState);
+                return;
             }
 
-            if (mConfiguration.mUsingIpReachabilityMonitor) {
-                mIpReachabilityMonitor = new IpReachabilityMonitor(
-                        mContext,
-                        mInterfaceName,
-                        new IpReachabilityMonitor.Callback() {
-                            @Override
-                            public void notifyLost(InetAddress ip, String logMsg) {
-                                mCallback.onReachabilityLost(logMsg);
-                            }
-                        },
-                        mAvoidBadWifiTracker);
+            if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) {
+                doImmediateProvisioningFailure(
+                        IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR);
+                transitionTo(mStoppingState);
+                return;
             }
         }
 
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index 07b26e8..6b919df 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -43,9 +43,12 @@
 import android.util.Slog;
 import android.util.TimedRemoteCaller;
 
+import com.android.internal.os.TransferPipe;
+
 import libcore.io.IoUtils;
 
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.List;
@@ -572,13 +575,11 @@
                     .append((mRemoteInstance != null) ? "true" : "false").println();
 
             pw.flush();
-
             try {
-                getRemoteInstanceLazy().asBinder().dump(fd, new String[]{prefix});
-            } catch (TimeoutException te) {
-                /* ignore */
-            } catch (RemoteException re) {
-                /* ignore */
+                TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd,
+                        new String[] { prefix });
+            } catch (IOException | TimeoutException | RemoteException e) {
+                pw.println("Failed to dump remote instance: " + e);
             }
         }
     }
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 65c740f..7474a64 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -68,7 +68,7 @@
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
 import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 4570a4b..d20e351 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -226,11 +226,11 @@
         if (insistent) {
             n.flags |= Notification.FLAG_INSISTENT;
         }
-        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
-                mScore, n, mUser, System.currentTimeMillis());
-        NotificationRecord r = new NotificationRecord(getContext(), sbn,
-                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "misc",
-                        NotificationManager.IMPORTANCE_DEFAULT));
+        NotificationChannel channel =
+                new NotificationChannel("test", "test", NotificationManager.IMPORTANCE_HIGH);
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, channel, id, mTag, mUid,
+                mPid, n, mUser, null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn);
         mService.addNotification(r);
         return r;
     }
diff --git a/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java b/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
index 22b674b..6c3f447 100644
--- a/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
@@ -31,6 +31,7 @@
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.os.UserHandle;
@@ -68,7 +69,10 @@
         if (groupKey != null) {
             nb.setGroup(groupKey);
         }
-        return new StatusBarNotification(pkg, pkg, id, tag, 0, 0, 0, nb.build(), user);
+        NotificationChannel channel =
+                new NotificationChannel("test", "test", NotificationManager.IMPORTANCE_LOW);
+        return new StatusBarNotification(pkg, pkg, channel, id, tag, 0, 0, nb.build(), user, null,
+                System.currentTimeMillis());
     }
 
     private StatusBarNotification getSbn(String pkg, int id, String tag,
diff --git a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
index 305b5e0..6bc9675 100644
--- a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -69,9 +69,9 @@
                 .setDefaults(Notification.DEFAULT_SOUND);
 
         Notification n = builder.build();
-        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, mId, mTag, mUid,
-                mPid, mScore, n, mUser, System.currentTimeMillis());
-        NotificationRecord r = new NotificationRecord(getContext(), sbn, channel);
+        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, channel, mId, mTag, mUid,
+                mPid, n, mUser, null, System.currentTimeMillis());
+        NotificationRecord r = new NotificationRecord(getContext(), sbn);
         return r;
     }
 
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 629146f..92c67b5 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -98,8 +98,8 @@
                 .setWhen(1205)
                 .build();
         mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortA, user), 
-                getDefaultChannel());
+                "package", "package", getDefaultChannel(), 1, null, 0, 0, mNotiGroupGSortA, user,
+                null, System.currentTimeMillis()));
 
         mNotiGroupGSortB = new Notification.Builder(getContext())
                 .setContentTitle("B")
@@ -108,24 +108,24 @@
                 .setWhen(1200)
                 .build();
         mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortB, user), 
-                getDefaultChannel());
+                "package", "package", getDefaultChannel(), 1, null, 0, 0, mNotiGroupGSortB, user,
+                null, System.currentTimeMillis()));
 
         mNotiNoGroup = new Notification.Builder(getContext())
                 .setContentTitle("C")
                 .setWhen(1201)
                 .build();
         mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup, user), 
-                getDefaultChannel());
+                "package", "package", getDefaultChannel(), 1, null, 0, 0, mNotiNoGroup, user,
+                null, System.currentTimeMillis()));
 
         mNotiNoGroup2 = new Notification.Builder(getContext())
                 .setContentTitle("D")
                 .setWhen(1202)
                 .build();
         mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup2, user), 
-                getDefaultChannel());
+                "package", "package", getDefaultChannel(), 1, null, 0, 0, mNotiNoGroup2, user,
+                null, System.currentTimeMillis()));
 
         mNotiNoGroupSortA = new Notification.Builder(getContext())
                 .setContentTitle("E")
@@ -133,8 +133,8 @@
                 .setSortKey("A")
                 .build();
         mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user), 
-                getDefaultChannel());
+                "package", "package", getDefaultChannel(), 1, null, 0, 0, mNotiNoGroupSortA, user,
+                null, System.currentTimeMillis()));
 
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index ffc45ea..7a3ee7f 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -178,9 +178,13 @@
                 .setWhen(1205)
                 .build();
         return new NotificationRecord(getContext(), new StatusBarNotification(
-                pkg, pkg, id, tag, 0, 0, 0, n, user),
-                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
-                        NotificationManager.IMPORTANCE_HIGH));
+                pkg, pkg, getDefaultChannel(), id, tag, 0, 0, n, user, null,
+                System.currentTimeMillis()));
+    }
+
+    private NotificationChannel getDefaultChannel() {
+        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+                NotificationManager.IMPORTANCE_LOW);
     }
 
 }
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java b/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
new file mode 100644
index 0000000..d6ee367
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsShellCommandTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
+
+import static com.android.internal.widget.LockPatternUtils.stringToPattern;
+
+import static junit.framework.Assert.*;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static java.io.FileDescriptor.*;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+
+/**
+ * Test class for {@link LockSettingsShellCommand}.
+ *
+ * runtest frameworks-services -c com.android.server.LockSettingsShellCommandTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class LockSettingsShellCommandTest {
+
+    private LockSettingsShellCommand mCommand;
+
+    private @Mock LockPatternUtils mLockPatternUtils;
+    private int mUserId;
+    private final Binder mBinder = new Binder();
+    private final ShellCallback mShellCallback = new ShellCallback();
+    private final ResultReceiver mResultReceiver = new ResultReceiver(
+            new Handler(Looper.getMainLooper()));
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final Context context = InstrumentationRegistry.getTargetContext();
+        mUserId = ActivityManager.getCurrentUser();
+        mCommand = new LockSettingsShellCommand(context, mLockPatternUtils);
+    }
+
+    @Test
+    public void testWrongPassword() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(false);
+        assertEquals(-1, mCommand.exec(mBinder, in, out, err,
+                new String[] { "set-pin", "--old", "1234" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils, never()).saveLockPassword(any(), any(), anyInt(), anyInt());
+    }
+
+    @Test
+    public void testChangePin() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(true);
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pin", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).saveLockPassword("4321", "1234", PASSWORD_QUALITY_NUMERIC,
+                mUserId);
+    }
+
+    @Test
+    public void testChangePassword() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.checkPassword("1234", mUserId)).thenReturn(true);
+        assertEquals(0,  mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-password", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).saveLockPassword("4321", "1234", PASSWORD_QUALITY_ALPHABETIC,
+                mUserId);
+    }
+
+    @Test
+    public void testChangePattern() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkPattern(stringToPattern("1234"), mUserId)).thenReturn(true);
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "set-pattern", "--old", "1234", "4321" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).saveLockPattern(stringToPattern("4321"), "1234", mUserId);
+    }
+
+    @Test
+    public void testClear() throws Exception {
+        when(mLockPatternUtils.isLockPatternEnabled(mUserId)).thenReturn(true);
+        when(mLockPatternUtils.isLockPasswordEnabled(mUserId)).thenReturn(false);
+        when(mLockPatternUtils.checkPattern(stringToPattern("1234"), mUserId)).thenReturn(true);
+        assertEquals(0, mCommand.exec(new Binder(), in, out, err,
+                new String[] { "clear", "--old", "1234" },
+                mShellCallback, mResultReceiver));
+        verify(mLockPatternUtils).clearLock(mUserId);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index d933cb3..772b2a2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -33,12 +33,11 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 /**
- * Tests for the {@link WindowState} class.
+ * Tests for the {@link AppWindowToken} class.
  *
  * Build/Install/Run:
  *  bit FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
new file mode 100644
index 0000000..0533efc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+import android.view.IWindow;
+import android.view.WindowManager;
+
+import java.util.ArrayList;
+
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
+import static android.app.AppOpsManager.OP_NONE;
+import static android.content.res.Configuration.EMPTY;
+import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for the {@link DisplayContent} class.
+ *
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class DisplayContentTests {
+
+    private static WindowManagerService sWm = null;
+    private final IWindow mIWindow = new TestIWindow();
+    private final Session mMockSession = mock(Session.class);
+    private Display mDisplay;
+    private int mNextStackId = FIRST_DYNAMIC_STACK_ID;
+    private int mNextTaskId = 0;
+
+    @Before
+    public void setUp() throws Exception {
+        final Context context = InstrumentationRegistry.getTargetContext();
+        sWm = TestWindowManagerPolicy.getWindowManagerService(context);
+        mDisplay = context.getDisplay();
+    }
+
+    @Test
+    public void testForAllWindows() throws Exception {
+        final DisplayContent dc = new DisplayContent(mDisplay, sWm, null, null);
+        final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, dc, "wallpaper");
+        final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, dc, "ime");
+        final WindowState imeDialogWindow = createWindow(null, TYPE_INPUT_METHOD_DIALOG, dc,
+                "ime dialog");
+        final WindowState statusBarWindow = createWindow(null, TYPE_STATUS_BAR, dc, "status bar");
+        final WindowState navBarWindow = createWindow(null, TYPE_NAVIGATION_BAR,
+                statusBarWindow.mToken, "nav bar");
+        final WindowState appWindow = createWindow(null, TYPE_BASE_APPLICATION, dc, "app");
+        final WindowState negChildAppWindow = createWindow(appWindow, TYPE_APPLICATION_MEDIA,
+                appWindow.mToken, "negative app child");
+        final WindowState posChildAppWindow = createWindow(appWindow,
+                TYPE_APPLICATION_ATTACHED_DIALOG, appWindow.mToken, "positive app child");
+        final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION, dc,
+                "exiting app");
+        final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+        exitingAppToken.mIsExiting = true;
+        exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);
+
+        final ArrayList<WindowState> windows = new ArrayList();
+
+        // Test forward traversal.
+        dc.forAllWindows(windows::add, false /* traverseTopToBottom */);
+
+        assertEquals(wallpaperWindow, windows.get(0));
+        assertEquals(exitingAppWindow, windows.get(1));
+        assertEquals(negChildAppWindow, windows.get(2));
+        assertEquals(appWindow, windows.get(3));
+        assertEquals(posChildAppWindow, windows.get(4));
+        assertEquals(statusBarWindow, windows.get(5));
+        assertEquals(navBarWindow, windows.get(6));
+        assertEquals(imeWindow, windows.get(7));
+        assertEquals(imeDialogWindow, windows.get(8));
+
+        // Test backward traversal.
+        windows.clear();
+        dc.forAllWindows(windows::add, true /* traverseTopToBottom */);
+
+        assertEquals(wallpaperWindow, windows.get(8));
+        assertEquals(exitingAppWindow, windows.get(7));
+        assertEquals(negChildAppWindow, windows.get(6));
+        assertEquals(appWindow, windows.get(5));
+        assertEquals(posChildAppWindow, windows.get(4));
+        assertEquals(statusBarWindow, windows.get(3));
+        assertEquals(navBarWindow, windows.get(2));
+        assertEquals(imeWindow, windows.get(1));
+        assertEquals(imeDialogWindow, windows.get(0));
+    }
+
+    private WindowToken createWindowToken(DisplayContent dc, int type) {
+        if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
+            return new WindowToken(sWm, mock(IBinder.class), type, false, dc);
+        }
+
+        final int stackId = mNextStackId++;
+        dc.addStackToDisplay(stackId, true);
+        final TaskStack stack = sWm.mStackIdToStack.get(stackId);
+        final Task task = new Task(mNextTaskId++, stack, 0, sWm, null, EMPTY, false);
+        stack.addTask(task, true);
+        final AppWindowToken token = new AppWindowToken(sWm, null, false, dc);
+        task.addAppToken(0, token, 0, false);
+        return token;
+    }
+
+    private WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
+        final WindowToken token = createWindowToken(dc, type);
+        return createWindow(parent, type, token, name);
+    }
+
+    private WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
+        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
+        attrs.setTitle(name);
+
+        final WindowState w = new WindowState(sWm, mMockSession, mIWindow, token, parent, OP_NONE,
+                0, attrs, 0, 0);
+        // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
+        // adding it to the token...
+        token.addWindow(w);
+        return w;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
index 5326a19..d12d672a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -39,7 +39,7 @@
 import static org.mockito.Mockito.mock;
 
 /**
- * Tests for the {@link WindowState} class.
+ * Tests for the {@link WindowToken} class.
  *
  * Build/Install/Run:
  *  bit FrameworksServicesTests:com.android.server.wm.WindowTokenTests
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index bb2b447..32f487b 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -233,7 +233,7 @@
      * @hide
      */
     /** @hide */
-    protected int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    protected Integer mSubId;
 
     private final Handler mHandler;
 
@@ -242,7 +242,7 @@
      * This class requires Looper.myLooper() not return null.
      */
     public PhoneStateListener() {
-        this(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, Looper.myLooper());
+        this(null, Looper.myLooper());
     }
 
     /**
@@ -251,7 +251,7 @@
      * @hide
      */
     public PhoneStateListener(Looper looper) {
-        this(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, looper);
+        this(null, looper);
     }
 
     /**
@@ -260,7 +260,7 @@
      * own non-null Looper use PhoneStateListener(int subId, Looper looper) below.
      * @hide
      */
-    public PhoneStateListener(int subId) {
+    public PhoneStateListener(Integer subId) {
         this(subId, Looper.myLooper());
     }
 
@@ -269,7 +269,7 @@
      * and non-null Looper.
      * @hide
      */
-    public PhoneStateListener(int subId, Looper looper) {
+    public PhoneStateListener(Integer subId, Looper looper) {
         if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
         mSubId = subId;
         mHandler = new Handler(looper) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index dcf2f06..20dd012 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -263,6 +263,22 @@
       return new TelephonyManager(mContext, subId);
     }
 
+    /**
+     * Create a new TelephonyManager object pinned to the subscription ID associated with the given
+     * phone account.
+     *
+     * @return a TelephonyManager that uses the given phone account for all calls, or {@code null}
+     * if the phone account does not correspond to a valid subscription ID.
+     */
+    @Nullable
+    public TelephonyManager createForPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+        int subId = getSubIdForPhoneAccountHandle(phoneAccountHandle);
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            return null;
+        }
+        return new TelephonyManager(mContext, subId);
+    }
+
     /** {@hide} */
     public boolean isMultiSimEnabled() {
         return (multiSimConfig.equals("dsds") || multiSimConfig.equals("dsda") ||
@@ -3019,6 +3035,12 @@
         if (mContext == null) return;
         try {
             Boolean notifyNow = (getITelephony() != null);
+            // If the listener has not explicitly set the subId (for example, created with the
+            // default constructor), replace the subId so it will listen to the account the
+            // telephony manager is created with.
+            if (listener.mSubId == null) {
+                listener.mSubId = mSubId;
+            }
             sRegistry.listenForSubscriber(listener.mSubId, getOpPackageName(),
                     listener.callback, events, notifyNow);
         } catch (RemoteException ex) {
@@ -5446,6 +5468,19 @@
         return retval;
     }
 
+    private int getSubIdForPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+        int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        try {
+            ITelecomService service = getTelecomService();
+            if (service != null) {
+                retval = getSubIdForPhoneAccount(service.getPhoneAccount(phoneAccountHandle));
+            }
+        } catch (RemoteException e) {
+        }
+
+        return retval;
+    }
+
     /**
      * Resets telephony manager settings back to factory defaults.
      *
@@ -5495,6 +5530,16 @@
     }
 
     /**
+     * Returns the current {@link ServiceState} information.
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     */
+    public ServiceState getServiceState() {
+        return getServiceStateForSubscriber(getSubId());
+    }
+
+    /**
      * Returns the service state information on specified subscription. Callers require
      * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
      * @hide
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 6ff0c5a..6a064d2 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -25,7 +25,7 @@
 import static com.android.server.connectivity.MetricsTestUtil.anIntArray;
 import static com.android.server.connectivity.MetricsTestUtil.b;
 import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent;
-import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
 
 import android.net.ConnectivityMetricsEvent;
 import android.net.metrics.ApfProgramEvent;
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index c7982b1..78d16d9 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -34,7 +34,7 @@
 import android.os.Parcelable;
 import android.util.Base64;
 
-import com.android.server.connectivity.metrics.IpConnectivityLogClass;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
 
 import junit.framework.TestCase;
 
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
index a30b362..9f7261d 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
@@ -59,13 +59,14 @@
     @Mock private INetworkStatsService mStatsService;
     @Mock private IControlsTethering mTetherHelper;
     @Mock private InterfaceConfiguration mInterfaceConfiguration;
+    @Mock private IPv6TetheringInterfaceServices mIPv6TetheringInterfaceServices;
 
     private final TestLooper mLooper = new TestLooper();
     private TetherInterfaceStateMachine mTestedSm;
 
     private void initStateMachine(int interfaceType) throws Exception {
         mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(), interfaceType,
-                mNMService, mStatsService, mTetherHelper);
+                mNMService, mStatsService, mTetherHelper, mIPv6TetheringInterfaceServices);
         mTestedSm.start();
         // Starting the state machine always puts us in a consistent state and notifies
         // the test of the world that we've changed from an unknown to available state.
@@ -91,7 +92,8 @@
     @Test
     public void startsOutAvailable() {
         mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
-                ConnectivityManager.TETHERING_BLUETOOTH, mNMService, mStatsService, mTetherHelper);
+                ConnectivityManager.TETHERING_BLUETOOTH, mNMService, mStatsService, mTetherHelper,
+                mIPv6TetheringInterfaceServices);
         mTestedSm.start();
         mLooper.dispatchAll();
         verify(mTetherHelper).notifyInterfaceStateChange(
@@ -274,4 +276,4 @@
                 upstreamIface);
         mLooper.dispatchAll();
     }
-}
\ No newline at end of file
+}
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index a06140c..f0b18e6 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -482,7 +482,9 @@
 
   void BackUp(int count) override { buffer_->BackUp(count); }
 
-  int64_t ByteCount() const override { return buffer_->size(); }
+  google::protobuf::int64 ByteCount() const override {
+    return buffer_->size();
+  }
 
   bool HadError() const override { return false; }
 
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index f1bc53e..7ab05b5 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -232,6 +232,13 @@
     }
 }*/
 
+#ifdef MAX
+#undef MAX
+#endif
+#ifdef ABS
+#undef ABS
+#endif
+
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 #define ABS(a) ((a) < 0 ? -(a) : (a))
 
diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h
index 01c9adb..aff1da3 100644
--- a/tools/aapt2/compile/Png.h
+++ b/tools/aapt2/compile/Png.h
@@ -62,8 +62,8 @@
   void BackUp(int count) override;
   bool Skip(int count) override;
 
-  int64_t ByteCount() const override {
-    return static_cast<int64_t>(window_start_);
+  google::protobuf::int64 ByteCount() const override {
+    return static_cast<google::protobuf::int64>(window_start_);
   }
 
   bool HadError() const override { return error_; }
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index 68db6b3..0d0e46d 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -361,7 +361,7 @@
 bool CompiledFileInputStream::ReadCompiledFile(pb::CompiledFile* out_val) {
   EnsureAlignedRead();
 
-  uint64_t pb_size = 0u;
+  google::protobuf::uint64 pb_size = 0u;
   if (!in_.ReadLittleEndian64(&pb_size)) {
     return false;
   }
@@ -389,7 +389,7 @@
                                                uint64_t* out_len) {
   EnsureAlignedRead();
 
-  uint64_t pb_size = 0u;
+  google::protobuf::uint64 pb_size = 0u;
   if (!in_.ReadLittleEndian64(&pb_size)) {
     return false;
   }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 017525b..bc38284 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.ScanSettings;
@@ -63,6 +64,12 @@
     int modifyPasspointManagementObject(String fqdn,
                                         in List<PasspointManagementObjectDefinition> mos);
 
+    boolean addPasspointConfiguration(in PasspointConfiguration config);
+
+    boolean removePasspointConfiguration(in String fqdn);
+
+    List<PasspointConfiguration> getPasspointConfigurations();
+
     void queryPasspointIcon(long bssid, String fileName);
 
     int matchProviderWithCurrentNetwork(String fqdn);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 8d5efba..e48f7bd 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -22,6 +22,7 @@
 import android.net.NetworkUtils;
 import android.text.TextUtils;
 
+import java.lang.Math;
 import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.net.UnknownHostException;
@@ -136,6 +137,15 @@
      */
     public double rxSuccessRate;
 
+    private static final long RESET_TIME_STAMP = Long.MIN_VALUE;
+    private static final long FILTER_TIME_CONSTANT = 3000;
+    /**
+     * This factor is used to adjust the rate output under the new algorithm
+     * such that the result is comparable to the previous algorithm.
+     */
+    private static final long OUTPUT_SCALE_FACTOR = 5000;
+    private long mLastPacketCountUpdateTimeStamp;
+
     /**
      * @hide
      */
@@ -157,10 +167,9 @@
     public int score;
 
     /**
-     * TODO: get actual timestamp and calculate true rates
      * @hide
      */
-    public void updatePacketRates(WifiLinkLayerStats stats) {
+    public void updatePacketRates(WifiLinkLayerStats stats, long timeStamp) {
         if (stats != null) {
             long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo;
             long txretries = stats.retries_be + stats.retries_bk
@@ -169,18 +178,28 @@
             long txbad = stats.lostmpdu_be + stats.lostmpdu_bk
                     + stats.lostmpdu_vi + stats.lostmpdu_vo;
 
-            if (txBad <= txbad
+            if (mLastPacketCountUpdateTimeStamp != RESET_TIME_STAMP
+                    && mLastPacketCountUpdateTimeStamp < timeStamp
+                    && txBad <= txbad
                     && txSuccess <= txgood
                     && rxSuccess <= rxgood
                     && txRetries <= txretries) {
-                txBadRate = (txBadRate * 0.5)
-                        + ((double) (txbad - txBad) * 0.5);
-                txSuccessRate = (txSuccessRate * 0.5)
-                        + ((double) (txgood - txSuccess) * 0.5);
-                rxSuccessRate = (rxSuccessRate * 0.5)
-                        + ((double) (rxgood - rxSuccess) * 0.5);
-                txRetriesRate = (txRetriesRate * 0.5)
-                        + ((double) (txretries - txRetries) * 0.5);
+                    long timeDelta = timeStamp - mLastPacketCountUpdateTimeStamp;
+                    double lastSampleWeight = Math.exp(-1.0 * timeDelta / FILTER_TIME_CONSTANT);
+                    double currentSampleWeight = 1.0 - lastSampleWeight;
+
+                    txBadRate = txBadRate * lastSampleWeight
+                        + (txbad - txBad) * OUTPUT_SCALE_FACTOR / timeDelta
+                        * currentSampleWeight;
+                    txSuccessRate = txSuccessRate * lastSampleWeight
+                        + (txgood - txSuccess) * OUTPUT_SCALE_FACTOR / timeDelta
+                        * currentSampleWeight;
+                    rxSuccessRate = rxSuccessRate * lastSampleWeight
+                        + (rxgood - rxSuccess) * OUTPUT_SCALE_FACTOR / timeDelta
+                        * currentSampleWeight;
+                    txRetriesRate = txRetriesRate * lastSampleWeight
+                        + (txretries - txRetries) * OUTPUT_SCALE_FACTOR / timeDelta
+                        * currentSampleWeight;
             } else {
                 txBadRate = 0;
                 txSuccessRate = 0;
@@ -191,6 +210,7 @@
             txSuccess = txgood;
             rxSuccess = rxgood;
             txRetries = txretries;
+            mLastPacketCountUpdateTimeStamp = timeStamp;
         } else {
             txBad = 0;
             txSuccess = 0;
@@ -200,6 +220,7 @@
             txSuccessRate = 0;
             rxSuccessRate = 0;
             txRetriesRate = 0;
+            mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
         }
     }
 
@@ -243,6 +264,7 @@
         mRssi = INVALID_RSSI;
         mLinkSpeed = -1;
         mFrequency = -1;
+        mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
     }
 
     /** @hide */
@@ -268,6 +290,7 @@
         badRssiCount = 0;
         linkStuckCount = 0;
         score = 0;
+        mLastPacketCountUpdateTimeStamp = RESET_TIME_STAMP;
     }
 
     /**
@@ -295,6 +318,8 @@
             txRetriesRate = source.txRetriesRate;
             txSuccessRate = source.txSuccessRate;
             rxSuccessRate = source.rxSuccessRate;
+            mLastPacketCountUpdateTimeStamp =
+                source.mLastPacketCountUpdateTimeStamp;
             score = source.score;
             badRssiCount = source.badRssiCount;
             lowRssiCount = source.lowRssiCount;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 18a580e..98a6ca5 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -26,6 +26,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -871,6 +872,56 @@
     }
 
     /**
+     * Add a Passpoint configuration.  The configuration provides a credential
+     * for connecting to Passpoint networks that are operated by the Passpoint
+     * service provider specified in the configuration.
+     *
+     * Each configuration is uniquely identified by its FQDN (Fully Qualified Domain
+     * Name).  In the case when there is an existing configuration with the same base
+     * domain, the new configuration will replace the existing configuration.
+     *
+     * @param config The Passpoint configuration to be added
+     * @return true on success or false on failure
+     * @hide
+     */
+    public boolean addPasspointConfiguration(PasspointConfiguration config) {
+        try {
+            return mService.addPasspointConfiguration(config);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Remove a Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
+     *
+     * @param fqdn The FQDN of the passpoint configuration to be removed
+     * @return true on success or false on failure
+     * @hide
+     */
+    public boolean removePasspointConfiguration(String fqdn) {
+        try {
+            return mService.removePasspointConfiguration(fqdn);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return the list of installed Passpoint configurations.
+     *
+     * @return A list of PasspointConfiguration or null
+     * @hide
+     */
+    public List<PasspointConfiguration> getPasspointConfigurations() {
+        try {
+            return mService.getPasspointConfigurations();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Query for a Hotspot 2.0 release 2 OSU icon
      * @param bssid The BSSID of the AP
      * @param fileName Icon file name
diff --git a/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java b/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
new file mode 100644
index 0000000..96db5d0
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/ConfigBuilder.java
@@ -0,0 +1,473 @@
+/**
+ * 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.net.wifi.hotspot2;
+
+import android.net.wifi.hotspot2.omadm.PPSMOParser;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+import android.util.Pair;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility class for building PasspointConfiguration from an installation file.
+ *
+ * @hide
+ */
+public final class ConfigBuilder {
+    private static final String TAG = "ConfigBuilder";
+
+    // Header names.
+    private static final String CONTENT_TYPE = "Content-Type";
+    private static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+
+    // MIME types.
+    private static final String TYPE_MULTIPART_MIXED = "multipart/mixed";
+    private static final String TYPE_WIFI_CONFIG = "application/x-wifi-config";
+    private static final String TYPE_PASSPOINT_PROFILE = "application/x-passpoint-profile";
+    private static final String TYPE_CA_CERT = "application/x-x509-ca-cert";
+    private static final String TYPE_PKCS12 = "application/x-pkcs12";
+
+    private static final String ENCODING_BASE64 = "base64";
+    private static final String BOUNDARY = "boundary=";
+
+    /**
+     * Class represent a MIME (Multipurpose Internet Mail Extension) part.
+     */
+    private static class MimePart {
+        /**
+         * Content type of the part.
+         */
+        public String type = null;
+
+        /**
+         * Decoded data.
+         */
+        public byte[] data = null;
+
+        /**
+         * Flag indicating if this is the last part (ending with --{boundary}--).
+         */
+        public boolean isLast = false;
+    }
+
+    /**
+     * Class represent the MIME (Multipurpose Internet Mail Extension) header.
+     */
+    private static class MimeHeader {
+        /**
+         * Content type.
+         */
+        public String contentType = null;
+
+        /**
+         * Boundary string (optional), only applies for the outter MIME header.
+         */
+        public String boundary = null;
+
+        /**
+         * Encoding type.
+         */
+        public String encodingType = null;
+    }
+
+
+    /**
+     * Parse the Hotspot 2.0 Release 1 configuration data into a {@link PasspointConfiguration}
+     * object.  The configuration data is a base64 encoded MIME multipart data.  Below is
+     * the format of the decoded message:
+     *
+     * Content-Type: multipart/mixed; boundary={boundary}
+     * Content-Transfer-Encoding: base64
+     *
+     * --{boundary}
+     * Content-Type: application/x-passpoint-profile
+     * Content-Transfer-Encoding: base64
+     *
+     * [base64 encoded Passpoint profile data]
+     * --{boundary}
+     * Content-Type: application/x-x509-ca-cert
+     * Content-Transfer-Encoding: base64
+     *
+     * [base64 encoded X509 CA certificate data]
+     * --{boundary}
+     * Content-Type: application/x-pkcs12
+     * Content-Transfer-Encoding: base64
+     *
+     * [base64 encoded PKCS#12 ASN.1 structure containing client certificate chain]
+     * --{boundary}
+     *
+     * @param mimeType MIME type of the encoded data.
+     * @param data A base64 encoded MIME multipart message containing the Passpoint profile
+     *             (required), CA (Certificate Authority) certificate (optional), and client
+     *             certificate chain (optional).
+     * @return {@link PasspointConfiguration}
+     */
+    public static PasspointConfiguration buildPasspointConfig(String mimeType, byte[] data) {
+        // Verify MIME type.
+        if (!TextUtils.equals(mimeType, TYPE_WIFI_CONFIG)) {
+            Log.e(TAG, "Unexpected MIME type: " + mimeType);
+            return null;
+        }
+
+        try {
+            // Decode the data.
+            byte[] decodedData = Base64.decode(new String(data, StandardCharsets.ISO_8859_1),
+                    Base64.DEFAULT);
+            Map<String, byte[]> mimeParts = parseMimeMultipartMessage(new LineNumberReader(
+                    new InputStreamReader(new ByteArrayInputStream(decodedData),
+                            StandardCharsets.ISO_8859_1)));
+            return createPasspointConfig(mimeParts);
+        } catch (IOException | IllegalArgumentException e) {
+            Log.e(TAG, "Failed to parse installation file: " + e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * Create a {@link PasspointConfiguration} object from list of MIME (Multipurpose Internet
+     * Mail Extension) parts.
+     *
+     * @param mimeParts Map of content type and content data.
+     * @return {@link PasspointConfiguration}
+     * @throws IOException
+     */
+    private static PasspointConfiguration createPasspointConfig(Map<String, byte[]> mimeParts)
+            throws IOException {
+        byte[] profileData = mimeParts.get(TYPE_PASSPOINT_PROFILE);
+        if (profileData == null) {
+            throw new IOException("Missing Passpoint Profile");
+        }
+
+        PasspointConfiguration config = PPSMOParser.parseMOText(new String(profileData));
+        if (config == null) {
+            throw new IOException("Failed to parse Passpoint profile");
+        }
+
+        // Credential is needed for storing the certificates and private client key.
+        if (config.credential == null) {
+            throw new IOException("Passpoint profile missing credential");
+        }
+
+        // Parse CA (Certificate Authority) certificate.
+        byte[] caCertData = mimeParts.get(TYPE_CA_CERT);
+        if (caCertData != null) {
+            try {
+                config.credential.caCertificate = parseCACert(caCertData);
+            } catch (CertificateException e) {
+                throw new IOException("Failed to parse CA Certificate");
+            }
+        }
+
+        // Parse PKCS12 data for client private key and certificate chain.
+        byte[] pkcs12Data = mimeParts.get(TYPE_PKCS12);
+        if (pkcs12Data != null) {
+            try {
+                Pair<PrivateKey, List<X509Certificate>> clientKey = parsePkcs12(pkcs12Data);
+                config.credential.clientPrivateKey = clientKey.first;
+                config.credential.clientCertificateChain =
+                        clientKey.second.toArray(new X509Certificate[clientKey.second.size()]);
+            } catch(GeneralSecurityException | IOException e) {
+                throw new IOException("Failed to parse PCKS12 string");
+            }
+        }
+        return config;
+    }
+
+    /**
+     * Parse a MIME (Multipurpose Internet Mail Extension) multipart message from the given
+     * input stream.
+     *
+     * @param in The input stream for reading the message data
+     * @return A map of a content type and content data pair
+     * @throws IOException
+     */
+    private static Map<String, byte[]> parseMimeMultipartMessage(LineNumberReader in)
+            throws IOException {
+        // Parse the outer MIME header.
+        MimeHeader header = parseHeaders(in);
+        if (!TextUtils.equals(header.contentType, TYPE_MULTIPART_MIXED)) {
+            throw new IOException("Invalid content type: " + header.contentType);
+        }
+        if (TextUtils.isEmpty(header.boundary)) {
+            throw new IOException("Missing boundary string");
+        }
+        if (!TextUtils.equals(header.encodingType, ENCODING_BASE64)) {
+            throw new IOException("Unexpected encoding: " + header.encodingType);
+        }
+
+        // Read pass the first boundary string.
+        for (;;) {
+            String line = in.readLine();
+            if (line == null) {
+                throw new IOException("Unexpected EOF before first boundary @ " +
+                        in.getLineNumber());
+            }
+            if (line.equals("--" + header.boundary)) {
+                break;
+            }
+        }
+
+        // Parse each MIME part.
+        Map<String, byte[]> mimeParts = new HashMap<>();
+        boolean isLast = false;
+        do {
+            MimePart mimePart = parseMimePart(in, header.boundary);
+            mimeParts.put(mimePart.type, mimePart.data);
+            isLast = mimePart.isLast;
+        } while(!isLast);
+        return mimeParts;
+    }
+
+    /**
+     * Parse a MIME (Multipurpose Internet Mail Extension) part.  We expect the data to
+     * be encoded in base64.
+     *
+     * @param in Input stream to read the data from
+     * @param boundary Boundary string indicate the end of the part
+     * @return {@link MimePart}
+     * @throws IOException
+     */
+    private static MimePart parseMimePart(LineNumberReader in, String boundary)
+            throws IOException {
+        MimeHeader header = parseHeaders(in);
+        // Expect encoding type to be base64.
+        if (!TextUtils.equals(header.encodingType, ENCODING_BASE64)) {
+            throw new IOException("Unexpected encoding type: " + header.encodingType);
+        }
+
+        // Check for a valid content type.
+        if (!TextUtils.equals(header.contentType, TYPE_PASSPOINT_PROFILE) &&
+                !TextUtils.equals(header.contentType, TYPE_CA_CERT) &&
+                !TextUtils.equals(header.contentType, TYPE_PKCS12)) {
+            throw new IOException("Unexpected content type: " + header.contentType);
+        }
+
+        StringBuilder text = new StringBuilder();
+        boolean isLast = false;
+        String partBoundary = "--" + boundary;
+        String endBoundary = partBoundary + "--";
+        for (;;) {
+            String line = in.readLine();
+            if (line == null) {
+                throw new IOException("Unexpected EOF file in body @ " + in.getLineNumber());
+            }
+            // Check for boundary line.
+            if (line.startsWith(partBoundary)) {
+                if (line.equals(endBoundary)) {
+                    isLast = true;
+                }
+                break;
+            }
+            text.append(line);
+        }
+
+        MimePart part = new MimePart();
+        part.type = header.contentType;
+        part.data = Base64.decode(text.toString(), Base64.DEFAULT);
+        part.isLast = isLast;
+        return part;
+    }
+
+    /**
+     * Parse a MIME (Multipurpose Internet Mail Extension) header from the input stream.
+     * @param in Input stream to read from.
+     * @return {@link MimeHeader}
+     * @throws IOException
+     */
+    private static MimeHeader parseHeaders(LineNumberReader in)
+            throws IOException {
+        MimeHeader header = new MimeHeader();
+
+        // Read the header from the input stream.
+        Map<String, String> headers = readHeaders(in);
+
+        // Parse each header.
+        for (Map.Entry<String, String> entry : headers.entrySet()) {
+            switch (entry.getKey()) {
+                case CONTENT_TYPE:
+                    Pair<String, String> value = parseContentType(entry.getValue());
+                    header.contentType = value.first;
+                    header.boundary = value.second;
+                    break;
+                case CONTENT_TRANSFER_ENCODING:
+                    header.encodingType = entry.getValue();
+                    break;
+                default:
+                    throw new IOException("Unexpected header: " + entry.getKey());
+            }
+        }
+        return header;
+    }
+
+    /**
+     * Parse the Content-Type header value.  The value will contain the content type string and
+     * an optional boundary string separated by a ";".  Below are examples of valid Content-Type
+     * header value:
+     *   multipart/mixed; boundary={boundary}
+     *   application/x-passpoint-profile
+     *
+     * @param contentType The Content-Type value string
+     * @return A pair of content type and boundary string
+     * @throws IOException
+     */
+    private static Pair<String, String> parseContentType(String contentType) throws IOException {
+        String[] attributes = contentType.toString().split(";");
+        String type = null;
+        String boundary = null;
+
+        if (attributes.length < 1 || attributes.length > 2) {
+            throw new IOException("Invalid Content-Type: " + contentType);
+        }
+
+        type = attributes[0].trim();
+        if (attributes.length == 2) {
+            boundary = attributes[1].trim();
+            if (!boundary.startsWith(BOUNDARY)) {
+                throw new IOException("Invalid Content-Type: " + contentType);
+            }
+            boundary = boundary.substring(BOUNDARY.length());
+            // Remove the leading and trailing quote if present.
+            if (boundary.length() > 1 && boundary.startsWith("\"") && boundary.endsWith("\"")) {
+                boundary = boundary.substring(1, boundary.length()-1);
+            }
+        }
+
+        return new Pair<String, String>(type, boundary);
+    }
+
+    /**
+     * Read the headers from the given input stream.  The header section is terminated by
+     * an empty line.
+     *
+     * @param in The input stream to read from
+     * @return Map of key-value pairs.
+     * @throws IOException
+     */
+    private static Map<String, String> readHeaders(LineNumberReader in)
+            throws IOException {
+        Map<String, String> headers = new HashMap<>();
+        String line;
+        String name = null;
+        StringBuilder value = null;
+        for (;;) {
+            line = in.readLine();
+            if (line == null) {
+                throw new IOException("Missing line @ " + in.getLineNumber());
+            }
+
+            // End of headers section.
+            if (line.length() == 0 || line.trim().length() == 0) {
+                // Save the previous header line.
+                if (name != null) {
+                    headers.put(name, value.toString());
+                }
+                break;
+            }
+
+            int nameEnd = line.indexOf(':');
+            if (nameEnd < 0) {
+                if (value != null) {
+                    // Continuation line for the header value.
+                    value.append(' ').append(line.trim());
+                } else {
+                    throw new IOException("Bad header line: '" + line + "' @ " +
+                            in.getLineNumber());
+                }
+            } else {
+                // New header line detected, make sure it doesn't start with a whitespace.
+                if (Character.isWhitespace(line.charAt(0))) {
+                    throw new IOException("Illegal blank prefix in header line '" + line +
+                            "' @ " + in.getLineNumber());
+                }
+
+                if (name != null) {
+                    // Save the previous header line.
+                    headers.put(name, value.toString());
+                }
+
+                // Setup the current header line.
+                name = line.substring(0, nameEnd).trim();
+                value = new StringBuilder();
+                value.append(line.substring(nameEnd+1).trim());
+            }
+        }
+        return headers;
+    }
+
+    /**
+     * Parse a CA (Certificate Authority) certificate data and convert it to a
+     * X509Certificate object.
+     *
+     * @param octets Certificate data
+     * @return X509Certificate
+     * @throws CertificateException
+     */
+    private static X509Certificate parseCACert(byte[] octets) throws CertificateException {
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+        return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(octets));
+    }
+
+    private static Pair<PrivateKey, List<X509Certificate>> parsePkcs12(byte[] octets)
+            throws GeneralSecurityException, IOException {
+        KeyStore ks = KeyStore.getInstance("PKCS12");
+        ByteArrayInputStream in = new ByteArrayInputStream(octets);
+        ks.load(in, new char[0]);
+        in.close();
+
+        // Only expects one set of key and certificate chain.
+        if (ks.size() != 1) {
+            throw new IOException("Unexpected key size: " + ks.size());
+        }
+
+        String alias = ks.aliases().nextElement();
+        if (alias == null) {
+            throw new IOException("No alias found");
+        }
+
+        PrivateKey clientKey = (PrivateKey) ks.getKey(alias, null);
+        List<X509Certificate> clientCertificateChain = null;
+        Certificate[] chain = ks.getCertificateChain(alias);
+        if (chain != null) {
+            clientCertificateChain = new ArrayList<>();
+            for (Certificate certificate : chain) {
+                if (!(certificate instanceof X509Certificate)) {
+                    throw new IOException("Unexpceted certificate type: " +
+                            certificate.getClass());
+                }
+                clientCertificateChain.add((X509Certificate) certificate);
+            }
+        }
+        return new Pair<PrivateKey, List<X509Certificate>>(clientKey, clientCertificateChain);
+    }
+}
\ No newline at end of file
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
new file mode 100644
index 0000000..8c1eb08
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
@@ -0,0 +1,85 @@
+Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
+dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
+cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
+IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
+SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
+YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
+UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
+V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
+M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
+MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
+VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
+RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
+QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
+QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
+bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
+MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
+Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
+ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
+YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
+VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
+YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
+RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
+bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
+MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
+MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
+UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
+eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
+QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
+OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
+dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
+S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
+K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
+dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
+TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
+SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
+WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
+VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
+MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
+Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
+V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
+a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
+eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
+VTJSbWx1WjJWeVVISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
+bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
+OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
+Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
+VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
+UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
+SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
+WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
+V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
+bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
+QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
+LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
+UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
+VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
+bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
+azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
+VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
+TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
+TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
+dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
+RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
+U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
+ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
+M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
+CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
+TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
+U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
+YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
+MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
+akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
+MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
+amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
+ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
+OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
+MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
+MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
+aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
+S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
+a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
+RFFWUkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
new file mode 100644
index 0000000..6d86dd5
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
@@ -0,0 +1,73 @@
+Content-Type: multipart/mixed; boundary={boundary}
+Content-Transfer-Encoding: base64
+
+--{boundary}
+Content-Type: application/x-passpoint-profile
+Content-Transfer-Encoding: base64
+
+PE1nbXRUcmVlIHhtbG5zPSJzeW5jbWw6ZG1kZGYxLjIiPgogIDxWZXJEVEQ+MS4yPC9WZXJEVEQ+
+CiAgPE5vZGU+CiAgICA8Tm9kZU5hbWU+UGVyUHJvdmlkZXJTdWJzY3JpcHRpb248L05vZGVOYW1l
+PgogICAgPFJUUHJvcGVydGllcz4KICAgICAgPFR5cGU+CiAgICAgICAgPERERk5hbWU+dXJuOndm
+YTptbzpob3RzcG90MmRvdDAtcGVycHJvdmlkZXJzdWJzY3JpcHRpb246MS4wPC9EREZOYW1lPgog
+ICAgICA8L1R5cGU+CiAgICA8L1JUUHJvcGVydGllcz4KICAgIDxOb2RlPgogICAgICA8Tm9kZU5h
+bWU+aTAwMTwvTm9kZU5hbWU+CiAgICAgIDxOb2RlPgogICAgICAgIDxOb2RlTmFtZT5Ib21lU1A8
+L05vZGVOYW1lPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPkZyaWVuZGx5TmFt
+ZTwvTm9kZU5hbWU+CiAgICAgICAgICA8VmFsdWU+Q2VudHVyeSBIb3VzZTwvVmFsdWU+CiAgICAg
+ICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPkZRRE48L05vZGVO
+YW1lPgogICAgICAgICAgPFZhbHVlPm1pNi5jby51azwvVmFsdWU+CiAgICAgICAgPC9Ob2RlPgog
+ICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlJvYW1pbmdDb25zb3J0aXVtT0k8L05v
+ZGVOYW1lPgogICAgICAgICAgPFZhbHVlPjExMjIzMyw0NDU1NjY8L1ZhbHVlPgogICAgICAgIDwv
+Tm9kZT4KICAgICAgPC9Ob2RlPgogICAgICA8Tm9kZT4KICAgICAgICA8Tm9kZU5hbWU+Q3JlZGVu
+dGlhbDwvTm9kZU5hbWU+CiAgICAgICAgPE5vZGU+CiAgICAgICAgICA8Tm9kZU5hbWU+UmVhbG08
+L05vZGVOYW1lPgogICAgICAgICAgPFZhbHVlPnNoYWtlbi5zdGlycmVkLmNvbTwvVmFsdWU+CiAg
+ICAgICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlVzZXJuYW1l
+UGFzc3dvcmQ8L05vZGVOYW1lPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2RlTmFt
+ZT5Vc2VybmFtZTwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxWYWx1ZT5qYW1lczwvVmFsdWU+CiAg
+ICAgICAgICA8L05vZGU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1lPlBh
+c3N3b3JkPC9Ob2RlTmFtZT4KICAgICAgICAgICAgPFZhbHVlPlltOXVaREF3Tnc9PTwvVmFsdWU+
+CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1l
+PkVBUE1ldGhvZDwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxOb2RlPgogICAgICAgICAgICAgIDxO
+b2RlTmFtZT5FQVBUeXBlPC9Ob2RlTmFtZT4KICAgICAgICAgICAgICA8VmFsdWU+MjE8L1ZhbHVl
+PgogICAgICAgICAgICA8L05vZGU+CiAgICAgICAgICAgIDxOb2RlPgogICAgICAgICAgICAgIDxO
+b2RlTmFtZT5Jbm5lck1ldGhvZDwvTm9kZU5hbWU+CiAgICAgICAgICAgICAgPFZhbHVlPk1TLUNI
+QVAtVjI8L1ZhbHVlPgogICAgICAgICAgICA8L05vZGU+CiAgICAgICAgICA8L05vZGU+CiAgICAg
+ICAgPC9Ob2RlPgogICAgICAgIDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPkRpZ2l0YWxDZXJ0
+aWZpY2F0ZTwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1l
+PkNlcnRpZmljYXRlVHlwZTwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxWYWx1ZT54NTA5djM8L1Zh
+bHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2Rl
+TmFtZT5DZXJ0U0hBMjU2RmluZ2VyUHJpbnQ8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+
+MWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYx
+ZjFmMWYxZjwvVmFsdWU+CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgPC9Ob2RlPgogICAgICAg
+IDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlNJTTwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9k
+ZT4KICAgICAgICAgICAgPE5vZGVOYW1lPklNU0k8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFs
+dWU+aW1zaTwvVmFsdWU+CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgICA8Tm9kZT4KICAgICAg
+ICAgICAgPE5vZGVOYW1lPkVBUFR5cGU8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+MjQ8
+L1ZhbHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgIDwvTm9kZT4KICAgICAgPC9Ob2RlPgog
+ICAgPC9Ob2RlPgogIDwvTm9kZT4KPC9NZ210VHJlZT4K
+
+--{boundary}
+Content-Type: application/x-x509-ca-cert
+Content-Transfer-Encoding: base64
+
+LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLRENDQWhDZ0F3SUJBZ0lKQUlMbEZkd3pM
+VnVyTUEwR0NTcUdTSWIzRFFFQkN3VUFNQkl4RURBT0JnTlYKQkFNVEIwVkJVQ0JEUVRFd0hoY05N
+VFl3TVRFeU1URTFNREUxV2hjTk1qWXdNVEE1TVRFMU1ERTFXakFTTVJBdwpEZ1lEVlFRREV3ZEZR
+VkFnUTBFeE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnpuQVBV
+ejI2TXNhZTR3czQzY3pSNDEvSjJRdHJTSVpVS21WVXNWdW1EYllIclBOdlRYS1NNWEFjZXdPUkRR
+WVgKUnF2SHZwbjhDc2NCMStvR1hadkh3eGo0elYwV0tvSzJ6ZVhrYXUzdmN5bDNISUt1cEpmcTJU
+RUFDZWZWamowdApKVytYMzVQR1dwOS9INXpJVU5WTlZqUzdVbXM4NEl2S2hSQjg1MTJQQjlVeUhh
+Z1hZVlg1R1dwQWNWcHlmcmxSCkZJOVFkaGgrUGJrMHV5a3RkYmYvQ2RmZ0hPb2ViclR0d1Jsak0w
+b0R0WCsyQ3Y2ajB3Qks3aEQ4cFB2ZjErdXkKR3pjemlnQVUvNEt3N2VacXlkZjlCKzVSdXBSK0la
+aXBYNDF4RWlJcktSd3FpNTE3V1d6WGNqYUcyY05iZjQ1MQp4cEg1UG5WM2kxdHEwNGpNR1FVekZ3
+SURBUUFCbzRHQU1INHdIUVlEVlIwT0JCWUVGSXdYNHZzOEJpQmNTY29kCjVub1pIUk04RTQraU1F
+SUdBMVVkSXdRN01EbUFGSXdYNHZzOEJpQmNTY29kNW5vWkhSTThFNCtpb1Jha0ZEQVMKTVJBd0Rn
+WURWUVFERXdkRlFWQWdRMEV4Z2drQWd1VVYzRE10VzZzd0RBWURWUjBUQkFVd0F3RUIvekFMQmdO
+VgpIUThFQkFNQ0FRWXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRmZRcU9UQTdSdjdLK2x1UTdw
+bmFzNEJZd0hFCjlHRVAvdW9odjZLT3kwVEdRRmJyUlRqRm9MVk5COUJaMXltTURaMC9USXdJVWM3
+d2k3YTh0NW1FcVlIMTUzd1cKYVdvb2lTanlMTGh1STRzTnJOQ090aXNkQnEycjJNRlh0NmgwbUFR
+WU9QdjhSOEs3L2ZnU3hHRnF6aHlObW1WTAoxcUJKbGR4MzRTcHdzVEFMUVZQYjRoR3dKelpmcjFQ
+Y3BFUXg2eE1uVGw4eEVXWkUzTXM5OXVhVXhiUXFJd1J1CkxnQU9rTkNtWTJtODlWaHphSEoxdVY4
+NUFkTS90RCtZc21sbm5qdDlMUkNlamJCaXBqSUdqT1hyZzFKUCtseFYKbXVNNHZIK1AvbWxteHNQ
+UHowZDY1YitFR21KWnBvTGtPL3RkTk52Q1l6akpwVEVXcEVzTzZOTWhLWW89Ci0tLS0tRU5EIENF
+UlRJRklDQVRFLS0tLS0K
+--{boundary}--
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64
new file mode 100644
index 0000000..906bfb3
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithInvalidContentType.base64
@@ -0,0 +1,85 @@
+Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
+dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
+cHBsaWNhdGlvbi9wYXNzcG9pbnQtcHJvZmlsZQpDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBi
+YXNlNjQKClBFMW5iWFJVY21WbElIaHRiRzV6UFNKemVXNWpiV3c2Wkcxa1pHWXhMaklpUGdvZ0lE
+eFdaWEpFVkVRK01TNHlQQzlXWlhKRVZFUSsKQ2lBZ1BFNXZaR1UrQ2lBZ0lDQThUbTlrWlU1aGJX
+VStVR1Z5VUhKdmRtbGtaWEpUZFdKelkzSnBjSFJwYjI0OEwwNXZaR1ZPWVcxbApQZ29nSUNBZ1BG
+SlVVSEp2Y0dWeWRHbGxjejRLSUNBZ0lDQWdQRlI1Y0dVK0NpQWdJQ0FnSUNBZ1BFUkVSazVoYldV
+K2RYSnVPbmRtCllUcHRienBvYjNSemNHOTBNbVJ2ZERBdGNHVnljSEp2ZG1sa1pYSnpkV0p6WTNK
+cGNIUnBiMjQ2TVM0d1BDOUVSRVpPWVcxbFBnb2cKSUNBZ0lDQThMMVI1Y0dVK0NpQWdJQ0E4TDFK
+VVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQThUbTlrWlU1aApiV1UrYVRB
+d01Ud3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0
+WlQ1SWIyMWxVMUE4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0Fn
+SUNBZ1BFNXZaR1ZPWVcxbFBrWnlhV1Z1Wkd4NVRtRnQKWlR3dlRtOWtaVTVoYldVK0NpQWdJQ0Fn
+SUNBZ0lDQThWbUZzZFdVK1EyVnVkSFZ5ZVNCSWIzVnpaVHd2Vm1Gc2RXVStDaUFnSUNBZwpJQ0Fn
+UEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQ
+a1pSUkU0OEwwNXZaR1ZPCllXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbTFwTmk1amJ5NTFh
+end2Vm1Gc2RXVStDaUFnSUNBZ0lDQWdQQzlPYjJSbFBnb2cKSUNBZ0lDQWdJRHhPYjJSbFBnb2dJ
+Q0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbEp2WVcxcGJtZERiMjV6YjNKMGFYVnRUMGs4TDA1dgpa
+R1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBqRXhNakl6TXl3ME5EVTFOalk4TDFaaGJI
+VmxQZ29nSUNBZ0lDQWdJRHd2ClRtOWtaVDRLSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBOFRt
+OWtaVDRLSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrUTNKbFpHVnUKZEdsaGJEd3ZUbTlrWlU1aGJX
+VStDaUFnSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStVbVZoYkcw
+OApMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbk5vWVd0bGJpNXpkR2x5Y21W
+a0xtTnZiVHd2Vm1Gc2RXVStDaUFnCklDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJS
+bFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbFZ6WlhKdVlXMWwKVUdGemMzZHZjbVE4TDA1
+dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJs
+VG1GdApaVDVWYzJWeWJtRnRaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gx
+WlQ1cVlXMWxjend2Vm1Gc2RXVStDaUFnCklDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0Fn
+SUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsQmgKYzNOM2IzSmtQQzlP
+YjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGxsdE9YVmFSRUYzVG5jOVBUd3ZW
+bUZzZFdVKwpDaUFnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pUNEtJ
+Q0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsClBrVkJVRTFsZEdodlpEd3ZUbTlrWlU1aGJXVStD
+aUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRa
+VDVGUVZCVWVYQmxQQzlPYjJSbFRtRnRaVDRLSUNBZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdVK01q
+RThMMVpoYkhWbApQZ29nSUNBZ0lDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lE
+eE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ0lDQWdJRHhPCmIyUmxUbUZ0WlQ1SmJtNWxjazFsZEdodlpE
+d3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGsxVExVTkkKUVZBdFZq
+SThMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4TDA1
+dlpHVStDaUFnSUNBZwpJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNB
+Z0lDQWdQRTV2WkdWT1lXMWxQa1JwWjJsMFlXeERaWEowCmFXWnBZMkYwWlR3dlRtOWtaVTVoYldV
+K0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtO
+bGNuUnBabWxqWVhSbFZIbHdaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeFdZV3gx
+WlQ1NE5UQTVkak04TDFaaApiSFZsUGdvZ0lDQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0Fn
+SUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEeE9iMlJsClRtRnRaVDVEWlhKMFUwaEJNalUy
+Um1sdVoyVnlVSEpwYm5ROEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVSsK
+TVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1N
+V1l4WmpGbU1XWXhaakZtTVdZeApaakZtTVdZeFpqd3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ0lDQThM
+MDV2WkdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0FnCklEeE9iMlJsUGdvZ0lDQWdJ
+Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBsTkpUVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNBOFRt
+OWsKWlQ0S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQa2xOVTBrOEwwNXZaR1ZPWVcxbFBn
+b2dJQ0FnSUNBZ0lDQWdJQ0E4Vm1GcwpkV1UrYVcxemFUd3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ0lD
+QThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0FnCklDQWdJQ0FnUEU1dlpH
+Vk9ZVzFsUGtWQlVGUjVjR1U4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+K01qUTgKTDFaaGJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHd2VG05
+a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnUEM5T2IyUmxQZ29nSUR3dlRtOWtaVDRLUEM5
+TloyMTBWSEpsWlQ0SwoKLS17Ym91bmRhcnl9CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24veC14
+NTA5LWNhLWNlcnQKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgpMUzB0TFMxQ1JV
+ZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VSTFJFTkRRV2hEWjBGM1NVSkJaMGxLUVVs
+TWJFWmtkM3BNClZuVnlUVUV3UjBOVGNVZFRTV0l6UkZGRlFrTjNWVUZOUWtsNFJVUkJUMEpuVGxZ
+S1FrRk5WRUl3VmtKVlEwSkVVVlJGZDBob1kwNU4KVkZsM1RWUkZlVTFVUlRGTlJFVXhWMmhqVGsx
+cVdYZE5WRUUxVFZSRk1VMUVSVEZYYWtGVFRWSkJkd3BFWjFsRVZsRlJSRVYzWkVaUgpWa0ZuVVRC
+RmVFMUpTVUpKYWtGT1FtZHJjV2hyYVVjNWR6QkNRVkZGUmtGQlQwTkJVVGhCVFVsSlFrTm5TME5C
+VVVWQkNucHVRVkJWCmVqSTJUWE5oWlRSM2N6UXpZM3BTTkRFdlNqSlJkSEpUU1ZwVlMyMVdWWE5X
+ZFcxRVlsbEljbEJPZGxSWVMxTk5XRUZqWlhkUFVrUlIKV1ZnS1VuRjJTSFp3YmpoRGMyTkNNU3R2
+UjFoYWRraDNlR28wZWxZd1YwdHZTeko2WlZocllYVXpkbU41YkROSVNVdDFjRXBtY1RKVQpSVUZE
+WldaV2Ftb3dkQXBLVnl0WU16VlFSMWR3T1M5SU5YcEpWVTVXVGxacVV6ZFZiWE00TkVsMlMyaFNR
+amcxTVRKUVFqbFZlVWhoCloxaFpWbGcxUjFkd1FXTldjSGxtY214U0NrWkpPVkZrYUdnclVHSnJN
+SFY1YTNSa1ltWXZRMlJtWjBoUGIyVmljbFIwZDFKc2FrMHcKYjBSMFdDc3lRM1kyYWpCM1FrczNh
+RVE0Y0ZCMlpqRXJkWGtLUjNwamVtbG5RVlV2TkV0M04yVmFjWGxrWmpsQ0t6VlNkWEJTSzBsYQph
+WEJZTkRGNFJXbEpja3RTZDNGcE5URTNWMWQ2V0dOcVlVY3lZMDVpWmpRMU1RcDRjRWcxVUc1V00y
+a3hkSEV3TkdwTlIxRlZla1ozClNVUkJVVUZDYnpSSFFVMUlOSGRJVVZsRVZsSXdUMEpDV1VWR1NY
+ZFlOSFp6T0VKcFFtTlRZMjlrQ2pWdWIxcElVazA0UlRRcmFVMUYKU1VkQk1WVmtTWGRSTjAxRWJV
+RkdTWGRZTkhaek9FSnBRbU5UWTI5a05XNXZXa2hTVFRoRk5DdHBiMUpoYTBaRVFWTUtUVkpCZDBS
+bgpXVVJXVVZGRVJYZGtSbEZXUVdkUk1FVjRaMmRyUVdkMVZWWXpSRTEwVnpaemQwUkJXVVJXVWpC
+VVFrRlZkMEYzUlVJdmVrRk1RbWRPClZncElVVGhGUWtGTlEwRlJXWGRFVVZsS1MyOWFTV2gyWTA1
+QlVVVk1RbEZCUkdkblJVSkJSbVpSY1U5VVFUZFNkamRMSzJ4MVVUZHcKYm1Gek5FSlpkMGhGQ2ps
+SFJWQXZkVzlvZGpaTFQza3dWRWRSUm1KeVVsUnFSbTlNVms1Q09VSmFNWGx0VFVSYU1DOVVTWGRK
+VldNMwpkMmszWVRoME5XMUZjVmxJTVRVemQxY0tZVmR2YjJsVGFubE1UR2gxU1RSelRuSk9RMDkw
+YVhOa1FuRXljakpOUmxoME5tZ3diVUZSCldVOVFkamhTT0VzM0wyWm5VM2hIUm5GNmFIbE9iVzFX
+VEFveGNVSktiR1I0TXpSVGNIZHpWRUZNVVZaUVlqUm9SM2RLZWxwbWNqRlEKWTNCRlVYZzJlRTF1
+Vkd3NGVFVlhXa1V6VFhNNU9YVmhWWGhpVVhGSmQxSjFDa3huUVU5clRrTnRXVEp0T0RsV2FIcGhT
+RW94ZFZZNApOVUZrVFM5MFJDdFpjMjFzYm01cWREbE1Va05sYW1KQ2FYQnFTVWRxVDFoeVp6RktV
+Q3RzZUZZS2JYVk5OSFpJSzFBdmJXeHRlSE5RClVIb3daRFkxWWl0RlIyMUtXbkJ2VEd0UEwzUmtU
+azUyUTFsNmFrcHdWRVZYY0VWelR6Wk9UV2hMV1c4OUNpMHRMUzB0UlU1RUlFTkYKVWxSSlJrbERR
+VlJGTFMwdExTMEsKLS17Ym91bmRhcnl9LS0K
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64
new file mode 100644
index 0000000..3fa97d1
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithMissingBoundary.base64
@@ -0,0 +1,85 @@
+Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
+dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
+cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
+IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
+SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
+YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
+UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
+V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
+M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
+MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
+VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
+RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
+QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
+QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
+bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
+MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
+Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
+ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
+YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
+VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
+YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
+RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
+bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
+MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
+MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
+UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
+eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
+QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
+OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
+dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
+S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
+K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
+dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
+TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
+SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
+WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
+VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
+MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
+Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
+V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
+a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
+eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
+VTJSbWx1WjJWeVVISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
+bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
+OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
+Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
+VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
+UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
+SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
+WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
+V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
+bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
+QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
+LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
+UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
+VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
+bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
+azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
+VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
+TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
+TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
+dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
+RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
+U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
+ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
+M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
+CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
+TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
+U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
+YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
+MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
+akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
+MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
+amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
+ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
+OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
+MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
+MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
+aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
+S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
+a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
+RFFWUkZMUzB0TFMwSwo=
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64
new file mode 100644
index 0000000..975f8e5
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithNonBase64Part.base64
@@ -0,0 +1,85 @@
+Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
+dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTMyCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
+cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
+IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
+SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
+YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
+UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
+V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
+M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
+MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
+VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
+RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
+QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
+QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
+bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
+MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
+Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
+ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
+YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
+VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
+YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
+RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
+bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
+MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
+MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
+UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
+eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
+QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
+OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
+dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
+S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
+K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
+dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
+TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
+SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
+WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
+VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
+MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
+Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
+V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
+a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
+eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
+QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
+VTJSbWx1WjJWeVVISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
+bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
+OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
+Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
+VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
+UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
+SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
+WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
+V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
+bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
+QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
+LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
+UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
+VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
+bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
+azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
+VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
+TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
+TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
+dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
+RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
+U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
+ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
+M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
+CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
+TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
+U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
+YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
+MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
+akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
+MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
+amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
+ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
+OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
+MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
+MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
+aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
+S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
+a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
+RFFWUkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithoutProfile.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithoutProfile.base64
new file mode 100644
index 0000000..833c527
--- /dev/null
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithoutProfile.base64
@@ -0,0 +1,31 @@
+Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
+dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
+cHBsaWNhdGlvbi94LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNl
+NjQKCkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERa
+MEYzU1VKQlowbEtRVWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5R
+a2w0UlVSQlQwSm5UbFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVS
+VEZOUkVVeFYyaGpUazFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJF
+VjNaRVpSClZrRm5VVEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVU
+aEJUVWxKUWtOblMwTkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRI
+SlRTVnBWUzIxV1ZYTldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNI
+WndiamhEYzJOQ01TdHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0
+MWNFcG1jVEpVClJVRkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpk
+VmJYTTRORWwyUzJoU1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2ta
+Sk9WRmthR2dyVUdKck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0Nz
+eVEzWTJhakIzUWtzM2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxD
+S3pWU2RYQlNLMGxhCmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalEx
+TVFwNGNFZzFVRzVXTTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxF
+VmxJd1QwSkNXVVZHU1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRC
+TVZWa1NYZFJOMDFFYlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhh
+MFpFUVZNS1RWSkJkMFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBW
+elp6ZDBSQldVUldVakJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVV
+VmxLUzI5YVNXaDJZMDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpi
+bUZ6TkVKWmQwaEZDamxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1Y
+bHRUVVJhTUM5VVNYZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRH
+aDFTVFJ6VG5KT1EwOTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUz
+aEhSbkY2YUhsT2JXMVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pG
+UQpZM0JGVVhnMmVFMXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtO
+dFdUSnRPRGxXYUhwaFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhC
+cVNVZHFUMWh5WnpGS1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIx
+S1duQnZUR3RQTDNSa1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVF
+SUVORgpVbFJKUmtsRFFWUkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
diff --git a/wifi/tests/assets/hsr1/README.txt b/wifi/tests/assets/hsr1/README.txt
new file mode 100644
index 0000000..d1f8384
--- /dev/null
+++ b/wifi/tests/assets/hsr1/README.txt
@@ -0,0 +1,5 @@
+HSR1ProfileWithCACert.conf - unencoded installation file that contains a Passpoint profile and a CA Certificate
+HSR1ProfileWithCACert.base64 - base64 encoded of the data contained in HSR1ProfileWithCAWith.conf
+HSR1ProfileWithNonBase64Part.base64 - base64 encoded installation file that contains a part of non-base64 encoding type
+HSR1ProfileWithMissingBoundary.base64 - base64 encoded installation file with missing end-boundary in the MIME data
+HSR1ProfileWithInvalidContentType.base64 - base64 encoded installation file with that contains a MIME part with an invalid content type.
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
new file mode 100644
index 0000000..6095929
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/ConfigBuilderTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.net.wifi.hotspot2;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.net.wifi.FakeKeys;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSP;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.ConfigBuilder}.
+ */
+@SmallTest
+public class ConfigBuilderTest {
+    /**
+     * Hotspot 2.0 Release 1 installation file that contains a Passpoint profile and a
+     * CA (Certificate Authority) X.509 certificate {@link FakeKeys#CA_CERT0}.
+     */
+    private static final String PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT =
+            "assets/hsr1/HSR1ProfileWithCACert.base64";
+    private static final String PASSPOINT_INSTALLATION_FILE_WITH_UNENCODED_DATA =
+            "assets/hsr1/HSR1ProfileWithCACert.conf";
+    private static final String PASSPOINT_INSTALLATION_FILE_WITH_INVALID_PART =
+            "assets/hsr1/HSR1ProfileWithNonBase64Part.base64";
+    private static final String PASSPOINT_INSTALLATION_FILE_WITH_MISSING_BOUNDARY =
+            "assets/hsr1/HSR1ProfileWithMissingBoundary.base64";
+    private static final String PASSPOINT_INSTALLATION_FILE_WITH_INVALID_CONTENT_TYPE =
+            "assets/hsr1/HSR1ProfileWithInvalidContentType.base64";
+    private static final String PASSPOINT_INSTALLATION_FILE_WITHOUT_PROFILE =
+            "assets/hsr1/HSR1ProfileWithoutProfile.base64";
+
+    /**
+     * Read the content of the given resource file into a String.
+     *
+     * @param filename String name of the file
+     * @return String
+     * @throws IOException
+     */
+    private String loadResourceFile(String filename) throws IOException {
+        InputStream in = getClass().getClassLoader().getResourceAsStream(filename);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+        StringBuilder builder = new StringBuilder();
+        String line;
+        while ((line = reader.readLine()) != null) {
+            builder.append(line).append("\n");
+        }
+
+        return builder.toString();
+    }
+
+    /**
+     * Generate a {@link PasspointConfiguration} that matches the configuration specified in the
+     * XML file {@link #PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT}.
+     *
+     * @return {@link PasspointConfiguration}
+     */
+    private PasspointConfiguration generateConfigurationFromProfile() {
+        PasspointConfiguration config = new PasspointConfiguration();
+
+        // HomeSP configuration.
+        config.homeSp = new HomeSP();
+        config.homeSp.friendlyName = "Century House";
+        config.homeSp.fqdn = "mi6.co.uk";
+        config.homeSp.roamingConsortiumOIs = new long[] {0x112233L, 0x445566L};
+
+        // Credential configuration.
+        config.credential = new Credential();
+        config.credential.realm = "shaken.stirred.com";
+        config.credential.userCredential = new Credential.UserCredential();
+        config.credential.userCredential.username = "james";
+        config.credential.userCredential.password = "Ym9uZDAwNw==";
+        config.credential.userCredential.eapType = 21;
+        config.credential.userCredential.nonEapInnerMethod = "MS-CHAP-V2";
+        config.credential.certCredential = new Credential.CertificateCredential();
+        config.credential.certCredential.certType = "x509v3";
+        config.credential.certCredential.certSha256FingerPrint = new byte[32];
+        Arrays.fill(config.credential.certCredential.certSha256FingerPrint, (byte)0x1f);
+        config.credential.simCredential = new Credential.SimCredential();
+        config.credential.simCredential.imsi = "imsi";
+        config.credential.simCredential.eapType = 24;
+        config.credential.caCertificate = FakeKeys.CA_CERT0;
+        return config;
+    }
+
+    /**
+     * Verify a valid installation file is parsed successfully with the matching contents.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFile() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT);
+        PasspointConfiguration expectedConfig = generateConfigurationFromProfile();
+        PasspointConfiguration actualConfig =
+                ConfigBuilder.buildPasspointConfig(
+                        "application/x-wifi-config", configStr.getBytes());
+        assertTrue(actualConfig.equals(expectedConfig));
+    }
+
+    /**
+     * Verify that parsing an installation file with invalid MIME type will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithInvalidMimeType() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT);
+        assertNull(ConfigBuilder.buildPasspointConfig(
+                "application/wifi-config", configStr.getBytes()));
+    }
+
+    /**
+     * Verify that parsing an un-encoded installation file will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithUnencodedData() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_UNENCODED_DATA);
+        assertNull(ConfigBuilder.buildPasspointConfig(
+                "application/x-wifi-config", configStr.getBytes()));
+    }
+
+    /**
+     * Verify that parsing an installation file that contains a non-base64 part will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithInvalidPart() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_INVALID_PART);
+        assertNull(ConfigBuilder.buildPasspointConfig(
+                "application/x-wifi-config", configStr.getBytes()));
+    }
+
+    /**
+     * Verify that parsing an installation file that contains a missing boundary string will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithMissingBoundary() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_MISSING_BOUNDARY);
+        assertNull(ConfigBuilder.buildPasspointConfig(
+                "application/x-wifi-config", configStr.getBytes()));
+    }
+
+    /**
+     * Verify that parsing an installation file that contains a MIME part with an invalid content
+     * type will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithInvalidContentType() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_INVALID_CONTENT_TYPE);
+        assertNull(ConfigBuilder.buildPasspointConfig(
+                "application/x-wifi-config", configStr.getBytes()));
+    }
+
+    /**
+     * Verify that parsing an installation file that doesn't contain a Passpoint profile will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void parseConfigFileWithoutPasspointProfile() throws Exception {
+        String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITHOUT_PROFILE);
+        assertNull(ConfigBuilder.buildPasspointConfig(
+                "application/x-wifi-config", configStr.getBytes()));
+    }
+}
\ No newline at end of file