Merge "Update docs to better document PhoneAccountHandle" into nyc-dev
diff --git a/Android.mk b/Android.mk
index 165aed9..cf6d946 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,7 +42,7 @@
 
 # EventLogTags files.
 LOCAL_SRC_FILES += \
-       core/java/android/auditing/SecurityLogTags.logtags \
+       core/java/android/app/admin/SecurityLogTags.logtags \
        core/java/android/content/EventLogTags.logtags \
        core/java/android/speech/tts/EventLogTags.logtags \
        core/java/android/webkit/EventLogTags.logtags \
diff --git a/api/current.txt b/api/current.txt
index 5b3c731..a66aac3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -443,6 +443,7 @@
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultHeight = 16844021; // 0x10104f5
+    field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -462,6 +463,7 @@
     field public static final int dialogTheme = 16843528; // 0x1010308
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
+    field public static final int directBootAware = 16844038; // 0x1010506
     field public static final int direction = 16843217; // 0x10101d1
     field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
@@ -510,7 +512,6 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final int endX = 16844051; // 0x1010513
@@ -559,6 +560,7 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -574,7 +576,6 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
-    field public static final int forceDeviceEncrypted = 16844037; // 0x1010505
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -943,6 +944,8 @@
     field public static final int popupBackground = 16843126; // 0x1010176
     field public static final int popupCharacters = 16843332; // 0x1010244
     field public static final int popupElevation = 16843916; // 0x101048c
+    field public static final int popupEnterTransition = 16844065; // 0x1010521
+    field public static final int popupExitTransition = 16844066; // 0x1010522
     field public static final int popupKeyboard = 16843331; // 0x1010243
     field public static final int popupLayout = 16843323; // 0x101023b
     field public static final int popupMenuStyle = 16843520; // 0x1010300
@@ -2753,14 +2756,10 @@
   }
 
   public final class GestureDescription {
-    method public static android.accessibilityservice.GestureDescription createClick(int, int);
-    method public static android.accessibilityservice.GestureDescription createLongClick(int, int);
-    method public static android.accessibilityservice.GestureDescription createPinch(int, int, int, int, float, long);
-    method public static android.accessibilityservice.GestureDescription createSwipe(int, int, int, int, long);
+    method public static long getMaxGestureDuration();
+    method public static int getMaxStrokeCount();
     method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(int);
     method public int getStrokeCount();
-    field public static final long MAX_GESTURE_DURATION_MS = 60000L; // 0xea60L
-    field public static final int MAX_STROKE_COUNT = 10; // 0xa
   }
 
   public static class GestureDescription.Builder {
@@ -3536,7 +3535,6 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
@@ -4218,7 +4216,6 @@
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5852,7 +5849,6 @@
     method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5901,6 +5897,7 @@
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void reboot(android.content.ComponentName);
@@ -5910,8 +5907,8 @@
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5923,7 +5920,6 @@
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -5956,6 +5952,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6041,6 +6038,27 @@
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6245,6 +6263,8 @@
     method public long getIntervalMillis();
     method public long getMaxExecutionDelayMillis();
     method public long getMinLatencyMillis();
+    method public static final long getMinimumFlex();
+    method public static final long getMinimumPeriod();
     method public int getNetworkType();
     method public android.content.ComponentName getService();
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
@@ -6258,8 +6278,6 @@
     field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
-    field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
-    field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6581,31 +6599,6 @@
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -7979,7 +7972,7 @@
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
     method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public abstract android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
@@ -8024,8 +8017,6 @@
     method public abstract java.lang.String getPackageResourcePath();
     method public abstract android.content.res.Resources getResources();
     method public abstract android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
-    method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
-    method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
@@ -8037,10 +8028,10 @@
     method public abstract deprecated int getWallpaperDesiredMinimumHeight();
     method public abstract deprecated int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public abstract boolean isDeviceEncryptedStorage();
+    method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public abstract boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public abstract boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
     method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -8175,7 +8166,7 @@
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public deprecated void clearWallpaper() throws java.io.IOException;
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -8227,9 +8218,9 @@
     method public deprecated int getWallpaperDesiredMinimumHeight();
     method public deprecated int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9320,10 +9311,9 @@
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
     field public int compatibleWidthLimitDp;
-    field public java.lang.String credentialEncryptedDataDir;
     field public java.lang.String dataDir;
     field public int descriptionRes;
-    field public java.lang.String deviceEncryptedDataDir;
+    field public java.lang.String deviceProtectedDataDir;
     field public boolean enabled;
     field public int flags;
     field public int largestWidthLimitDp;
@@ -9360,8 +9350,8 @@
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
+    field public boolean directBootAware;
     field public boolean enabled;
-    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9832,11 +9822,10 @@
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
+    field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
-    field public static final int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -19267,7 +19256,6 @@
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
-    method public boolean isPseudorangeRateCorrected();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
     field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -19285,9 +19273,6 @@
     field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssMeasurementsEvent implements android.os.Parcelable {
     ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
     method public int describeContents();
@@ -19306,9 +19291,6 @@
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GnssMeasurementsEvent.GnssMeasurementsStatus implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
@@ -19334,9 +19316,6 @@
     field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssNavigationMessageEvent implements android.os.Parcelable {
     ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
     method public int describeContents();
@@ -19354,9 +19333,6 @@
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GnssNavigationMessageEvent.GnssNavigationMessageStatus implements java.lang.annotation.Annotation {
-  }
-
   public abstract interface GnssNmeaListener {
     method public abstract void onNmeaReceived(long, java.lang.String);
   }
@@ -19380,9 +19356,6 @@
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
-  }
-
   public abstract class GnssStatusCallback {
     ctor public GnssStatusCallback();
     method public void onFirstFix(int);
@@ -23090,6 +23063,7 @@
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
     method public void notifyTuned(android.net.Uri);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
     method public abstract void onStopRecording();
@@ -23107,6 +23081,7 @@
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyVideoAvailable();
     method public void notifyVideoUnavailable(int);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -23138,6 +23113,7 @@
   public class TvRecordingClient {
     ctor public TvRecordingClient(android.content.Context, java.lang.String, android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
     method public void release();
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void startRecording(android.net.Uri);
     method public void stopRecording();
     method public void tune(java.lang.String, android.net.Uri);
@@ -23199,6 +23175,7 @@
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void setCallback(android.media.tv.TvView.TvInputCallback);
     method public void setCaptionEnabled(boolean);
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
@@ -29372,10 +29349,6 @@
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
     method public boolean isUserUnlocked();
     method public boolean isUserUnlocked(android.os.UserHandle);
@@ -29606,6 +29579,7 @@
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
+    method public boolean isEncrypted(java.io.File);
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
@@ -29937,7 +29911,7 @@
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
     method public void setStorageDefault();
-    method public void setStorageDeviceEncrypted();
+    method public void setStorageDeviceProtected();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -36829,6 +36803,7 @@
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -37913,7 +37888,7 @@
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -37964,9 +37939,9 @@
     method public int getWallpaperDesiredMinimumHeight();
     method public int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -42593,7 +42568,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public void onVisibilityAggregated(android.view.View, int);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -43690,7 +43665,7 @@
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -47204,6 +47179,8 @@
     method public android.graphics.drawable.Drawable getBackground();
     method public android.view.View getContentView();
     method public float getElevation();
+    method public android.transition.Transition getEnterTransition();
+    method public android.transition.Transition getExitTransition();
     method public int getHeight();
     method public int getInputMethodMode();
     method public int getMaxAvailableHeight(android.view.View);
@@ -50697,6 +50674,7 @@
     method public float floatValue();
     method public static int hashCode(double);
     method public int intValue();
+    method public static boolean isFinite(double);
     method public static boolean isInfinite(double);
     method public boolean isInfinite();
     method public static boolean isNaN(double);
@@ -50778,6 +50756,7 @@
     method public float floatValue();
     method public static float intBitsToFloat(int);
     method public int intValue();
+    method public static boolean isFinite(float);
     method public static boolean isInfinite(float);
     method public boolean isInfinite();
     method public static boolean isNaN(float);
@@ -57355,6 +57334,7 @@
     method public E get(int);
     method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
@@ -57456,6 +57436,10 @@
     method public static void parallelSort(T[], int, int);
     method public static void parallelSort(T[], java.util.Comparator<? super T>);
     method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static void setAll(int[], java.util.function.IntUnaryOperator);
+    method public static void setAll(long[], java.util.function.IntToLongFunction);
+    method public static void setAll(double[], java.util.function.IntToDoubleFunction);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -57482,6 +57466,14 @@
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[]);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
+    method public static java.util.stream.Stream<T> stream(T[]);
+    method public static java.util.stream.Stream<T> stream(T[], int, int);
+    method public static java.util.stream.IntStream stream(int[]);
+    method public static java.util.stream.IntStream stream(int[], int, int);
+    method public static java.util.stream.LongStream stream(long[]);
+    method public static java.util.stream.LongStream stream(long[], int, int);
+    method public static java.util.stream.DoubleStream stream(double[]);
+    method public static java.util.stream.DoubleStream stream(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -57641,11 +57633,13 @@
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Iterator<E> iterator();
+    method public default java.util.stream.Stream<E> parallelStream();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
     method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
+    method public default java.util.stream.Stream<E> stream();
     method public abstract java.lang.Object[] toArray();
     method public abstract T[] toArray(T[]);
   }
@@ -58845,6 +58839,34 @@
     method public java.util.Spliterator<T> trySplit();
   }
 
+  public final class SplittableRandom {
+    ctor public SplittableRandom(long);
+    ctor public SplittableRandom();
+    method public java.util.stream.DoubleStream doubles(long);
+    method public java.util.stream.DoubleStream doubles();
+    method public java.util.stream.DoubleStream doubles(long, double, double);
+    method public java.util.stream.DoubleStream doubles(double, double);
+    method public java.util.stream.IntStream ints(long);
+    method public java.util.stream.IntStream ints();
+    method public java.util.stream.IntStream ints(long, int, int);
+    method public java.util.stream.IntStream ints(int, int);
+    method public java.util.stream.LongStream longs(long);
+    method public java.util.stream.LongStream longs();
+    method public java.util.stream.LongStream longs(long, long, long);
+    method public java.util.stream.LongStream longs(long, long);
+    method public boolean nextBoolean();
+    method public double nextDouble();
+    method public double nextDouble(double);
+    method public double nextDouble(double, double);
+    method public int nextInt();
+    method public int nextInt(int);
+    method public int nextInt(int, int);
+    method public long nextLong();
+    method public long nextLong(long);
+    method public long nextLong(long, long);
+    method public java.util.SplittableRandom split();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -60028,6 +60050,18 @@
 
   public class ThreadLocalRandom extends java.util.Random {
     method public static java.util.concurrent.ThreadLocalRandom current();
+    method public java.util.stream.DoubleStream doubles(long);
+    method public java.util.stream.DoubleStream doubles();
+    method public java.util.stream.DoubleStream doubles(long, double, double);
+    method public java.util.stream.DoubleStream doubles(double, double);
+    method public java.util.stream.IntStream ints(long);
+    method public java.util.stream.IntStream ints();
+    method public java.util.stream.IntStream ints(long, int, int);
+    method public java.util.stream.IntStream ints(int, int);
+    method public java.util.stream.LongStream longs(long);
+    method public java.util.stream.LongStream longs();
+    method public java.util.stream.LongStream longs(long, long, long);
+    method public java.util.stream.LongStream longs(long, long);
     method public double nextDouble(double);
     method public double nextDouble(double, double);
     method public int nextInt(int, int);
@@ -61429,6 +61463,292 @@
 
 }
 
+package java.util.stream {
+
+  public abstract interface BaseStream implements java.lang.AutoCloseable {
+    method public abstract void close();
+    method public abstract boolean isParallel();
+    method public abstract java.util.Iterator<T> iterator();
+    method public abstract S onClose(java.lang.Runnable);
+    method public abstract S parallel();
+    method public abstract S sequential();
+    method public abstract java.util.Spliterator<T> spliterator();
+    method public abstract S unordered();
+  }
+
+  public abstract interface Collector {
+    method public abstract java.util.function.BiConsumer<A, T> accumulator();
+    method public abstract java.util.Set<java.util.stream.Collector.Characteristics> characteristics();
+    method public abstract java.util.function.BinaryOperator<A> combiner();
+    method public abstract java.util.function.Function<A, R> finisher();
+    method public static java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
+    method public static java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
+    method public abstract java.util.function.Supplier<A> supplier();
+  }
+
+  public static final class Collector.Characteristics extends java.lang.Enum {
+    method public static java.util.stream.Collector.Characteristics valueOf(java.lang.String);
+    method public static final java.util.stream.Collector.Characteristics[] values();
+    enum_constant public static final java.util.stream.Collector.Characteristics CONCURRENT;
+    enum_constant public static final java.util.stream.Collector.Characteristics IDENTITY_FINISH;
+    enum_constant public static final java.util.stream.Collector.Characteristics UNORDERED;
+  }
+
+  public final class Collectors {
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Long> counting();
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining();
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence);
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public static java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
+    method public static java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static java.util.stream.Collector<T, ?, java.util.List<T>> toList();
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
+  }
+
+  public abstract interface DoubleStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.DoublePredicate);
+    method public abstract boolean anyMatch(java.util.function.DoublePredicate);
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Double> boxed();
+    method public static java.util.stream.DoubleStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
+    method public abstract long count();
+    method public abstract java.util.stream.DoubleStream distinct();
+    method public static java.util.stream.DoubleStream empty();
+    method public abstract java.util.stream.DoubleStream filter(java.util.function.DoublePredicate);
+    method public abstract java.util.OptionalDouble findAny();
+    method public abstract java.util.OptionalDouble findFirst();
+    method public abstract java.util.stream.DoubleStream flatMap(java.util.function.DoubleFunction<? extends java.util.stream.DoubleStream>);
+    method public abstract void forEach(java.util.function.DoubleConsumer);
+    method public abstract void forEachOrdered(java.util.function.DoubleConsumer);
+    method public static java.util.stream.DoubleStream generate(java.util.function.DoubleSupplier);
+    method public static java.util.stream.DoubleStream iterate(double, java.util.function.DoubleUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfDouble iterator();
+    method public abstract java.util.stream.DoubleStream limit(long);
+    method public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
+    method public abstract java.util.OptionalDouble max();
+    method public abstract java.util.OptionalDouble min();
+    method public abstract boolean noneMatch(java.util.function.DoublePredicate);
+    method public static java.util.stream.DoubleStream of(double);
+    method public static java.util.stream.DoubleStream of(double...);
+    method public abstract java.util.stream.DoubleStream parallel();
+    method public abstract java.util.stream.DoubleStream peek(java.util.function.DoubleConsumer);
+    method public abstract double reduce(double, java.util.function.DoubleBinaryOperator);
+    method public abstract java.util.OptionalDouble reduce(java.util.function.DoubleBinaryOperator);
+    method public abstract java.util.stream.DoubleStream sequential();
+    method public abstract java.util.stream.DoubleStream skip(long);
+    method public abstract java.util.stream.DoubleStream sorted();
+    method public abstract java.util.Spliterator.OfDouble spliterator();
+    method public abstract double sum();
+    method public abstract java.util.DoubleSummaryStatistics summaryStatistics();
+    method public abstract double[] toArray();
+  }
+
+  public static abstract interface DoubleStream.Builder implements java.util.function.DoubleConsumer {
+    method public abstract void accept(double);
+    method public default java.util.stream.DoubleStream.Builder add(double);
+    method public abstract java.util.stream.DoubleStream build();
+  }
+
+  public abstract interface IntStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.IntPredicate);
+    method public abstract boolean anyMatch(java.util.function.IntPredicate);
+    method public abstract java.util.stream.DoubleStream asDoubleStream();
+    method public abstract java.util.stream.LongStream asLongStream();
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Integer> boxed();
+    method public static java.util.stream.IntStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
+    method public abstract long count();
+    method public abstract java.util.stream.IntStream distinct();
+    method public static java.util.stream.IntStream empty();
+    method public abstract java.util.stream.IntStream filter(java.util.function.IntPredicate);
+    method public abstract java.util.OptionalInt findAny();
+    method public abstract java.util.OptionalInt findFirst();
+    method public abstract java.util.stream.IntStream flatMap(java.util.function.IntFunction<? extends java.util.stream.IntStream>);
+    method public abstract void forEach(java.util.function.IntConsumer);
+    method public abstract void forEachOrdered(java.util.function.IntConsumer);
+    method public static java.util.stream.IntStream generate(java.util.function.IntSupplier);
+    method public static java.util.stream.IntStream iterate(int, java.util.function.IntUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfInt iterator();
+    method public abstract java.util.stream.IntStream limit(long);
+    method public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
+    method public abstract java.util.OptionalInt max();
+    method public abstract java.util.OptionalInt min();
+    method public abstract boolean noneMatch(java.util.function.IntPredicate);
+    method public static java.util.stream.IntStream of(int);
+    method public static java.util.stream.IntStream of(int...);
+    method public abstract java.util.stream.IntStream parallel();
+    method public abstract java.util.stream.IntStream peek(java.util.function.IntConsumer);
+    method public static java.util.stream.IntStream range(int, int);
+    method public static java.util.stream.IntStream rangeClosed(int, int);
+    method public abstract int reduce(int, java.util.function.IntBinaryOperator);
+    method public abstract java.util.OptionalInt reduce(java.util.function.IntBinaryOperator);
+    method public abstract java.util.stream.IntStream sequential();
+    method public abstract java.util.stream.IntStream skip(long);
+    method public abstract java.util.stream.IntStream sorted();
+    method public abstract java.util.Spliterator.OfInt spliterator();
+    method public abstract int sum();
+    method public abstract java.util.IntSummaryStatistics summaryStatistics();
+    method public abstract int[] toArray();
+  }
+
+  public static abstract interface IntStream.Builder implements java.util.function.IntConsumer {
+    method public abstract void accept(int);
+    method public default java.util.stream.IntStream.Builder add(int);
+    method public abstract java.util.stream.IntStream build();
+  }
+
+  public abstract interface LongStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.LongPredicate);
+    method public abstract boolean anyMatch(java.util.function.LongPredicate);
+    method public abstract java.util.stream.DoubleStream asDoubleStream();
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Long> boxed();
+    method public static java.util.stream.LongStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
+    method public abstract long count();
+    method public abstract java.util.stream.LongStream distinct();
+    method public static java.util.stream.LongStream empty();
+    method public abstract java.util.stream.LongStream filter(java.util.function.LongPredicate);
+    method public abstract java.util.OptionalLong findAny();
+    method public abstract java.util.OptionalLong findFirst();
+    method public abstract java.util.stream.LongStream flatMap(java.util.function.LongFunction<? extends java.util.stream.LongStream>);
+    method public abstract void forEach(java.util.function.LongConsumer);
+    method public abstract void forEachOrdered(java.util.function.LongConsumer);
+    method public static java.util.stream.LongStream generate(java.util.function.LongSupplier);
+    method public static java.util.stream.LongStream iterate(long, java.util.function.LongUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfLong iterator();
+    method public abstract java.util.stream.LongStream limit(long);
+    method public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
+    method public abstract java.util.OptionalLong max();
+    method public abstract java.util.OptionalLong min();
+    method public abstract boolean noneMatch(java.util.function.LongPredicate);
+    method public static java.util.stream.LongStream of(long);
+    method public static java.util.stream.LongStream of(long...);
+    method public abstract java.util.stream.LongStream parallel();
+    method public abstract java.util.stream.LongStream peek(java.util.function.LongConsumer);
+    method public static java.util.stream.LongStream range(long, long);
+    method public static java.util.stream.LongStream rangeClosed(long, long);
+    method public abstract long reduce(long, java.util.function.LongBinaryOperator);
+    method public abstract java.util.OptionalLong reduce(java.util.function.LongBinaryOperator);
+    method public abstract java.util.stream.LongStream sequential();
+    method public abstract java.util.stream.LongStream skip(long);
+    method public abstract java.util.stream.LongStream sorted();
+    method public abstract java.util.Spliterator.OfLong spliterator();
+    method public abstract long sum();
+    method public abstract java.util.LongSummaryStatistics summaryStatistics();
+    method public abstract long[] toArray();
+  }
+
+  public static abstract interface LongStream.Builder implements java.util.function.LongConsumer {
+    method public abstract void accept(long);
+    method public default java.util.stream.LongStream.Builder add(long);
+    method public abstract java.util.stream.LongStream build();
+  }
+
+  public abstract interface Stream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.Predicate<? super T>);
+    method public abstract boolean anyMatch(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Stream.Builder<T> builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
+    method public abstract R collect(java.util.stream.Collector<? super T, A, R>);
+    method public static java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
+    method public abstract long count();
+    method public abstract java.util.stream.Stream<T> distinct();
+    method public static java.util.stream.Stream<T> empty();
+    method public abstract java.util.stream.Stream<T> filter(java.util.function.Predicate<? super T>);
+    method public abstract java.util.Optional<T> findAny();
+    method public abstract java.util.Optional<T> findFirst();
+    method public abstract java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
+    method public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function<? super T, ? extends java.util.stream.DoubleStream>);
+    method public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function<? super T, ? extends java.util.stream.IntStream>);
+    method public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function<? super T, ? extends java.util.stream.LongStream>);
+    method public abstract void forEach(java.util.function.Consumer<? super T>);
+    method public abstract void forEachOrdered(java.util.function.Consumer<? super T>);
+    method public static java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
+    method public static java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
+    method public abstract java.util.stream.Stream<T> limit(long);
+    method public abstract java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction<? super T>);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction<? super T>);
+    method public abstract java.util.Optional<T> max(java.util.Comparator<? super T>);
+    method public abstract java.util.Optional<T> min(java.util.Comparator<? super T>);
+    method public abstract boolean noneMatch(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Stream<T> of(T);
+    method public static java.util.stream.Stream<T> of(T...);
+    method public abstract java.util.stream.Stream<T> peek(java.util.function.Consumer<? super T>);
+    method public abstract T reduce(T, java.util.function.BinaryOperator<T>);
+    method public abstract java.util.Optional<T> reduce(java.util.function.BinaryOperator<T>);
+    method public abstract U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
+    method public abstract java.util.stream.Stream<T> skip(long);
+    method public abstract java.util.stream.Stream<T> sorted();
+    method public abstract java.util.stream.Stream<T> sorted(java.util.Comparator<? super T>);
+    method public abstract java.lang.Object[] toArray();
+    method public abstract A[] toArray(java.util.function.IntFunction<A[]>);
+  }
+
+  public static abstract interface Stream.Builder implements java.util.function.Consumer {
+    method public abstract void accept(T);
+    method public default java.util.stream.Stream.Builder<T> add(T);
+    method public abstract java.util.stream.Stream<T> build();
+  }
+
+  public final class StreamSupport {
+    method public static java.util.stream.DoubleStream doubleStream(java.util.Spliterator.OfDouble, boolean);
+    method public static java.util.stream.DoubleStream doubleStream(java.util.function.Supplier<? extends java.util.Spliterator.OfDouble>, int, boolean);
+    method public static java.util.stream.IntStream intStream(java.util.Spliterator.OfInt, boolean);
+    method public static java.util.stream.IntStream intStream(java.util.function.Supplier<? extends java.util.Spliterator.OfInt>, int, boolean);
+    method public static java.util.stream.LongStream longStream(java.util.Spliterator.OfLong, boolean);
+    method public static java.util.stream.LongStream longStream(java.util.function.Supplier<? extends java.util.Spliterator.OfLong>, int, boolean);
+    method public static java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
+    method public static java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
+  }
+
+}
+
 package java.util.zip {
 
   public class Adler32 implements java.util.zip.Checksum {
diff --git a/api/removed.txt b/api/removed.txt
index 8ac2d63..36c8ce5 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -17,12 +17,42 @@
 
 }
 
+package android.content {
+
+  public abstract class Context {
+    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
+    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
+    method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
+    method public deprecated boolean isCredentialEncryptedStorage();
+    method public deprecated boolean isDeviceEncryptedStorage();
+    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
+    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+  }
+
+}
+
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String credentialEncryptedDataDir;
+    field public deprecated java.lang.String deviceEncryptedDataDir;
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    field public deprecated boolean encryptionAware;
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public abstract class PackageManager {
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
+    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
+  }
+
 }
 
 package android.database {
@@ -98,6 +128,19 @@
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
+  }
+
+}
+
+package android.preference {
+
+  public class PreferenceManager {
+    method public deprecated void setStorageCredentialEncrypted();
+    method public deprecated void setStorageDeviceEncrypted();
   }
 
 }
diff --git a/api/system-current.txt b/api/system-current.txt
index 32fb87f..676dd38 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -538,6 +538,7 @@
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultHeight = 16844021; // 0x10104f5
+    field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -557,6 +558,7 @@
     field public static final int dialogTheme = 16843528; // 0x1010308
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
+    field public static final int directBootAware = 16844038; // 0x1010506
     field public static final int direction = 16843217; // 0x10101d1
     field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
@@ -605,7 +607,6 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final int endX = 16844051; // 0x1010513
@@ -654,6 +655,7 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -669,7 +671,6 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
-    field public static final int forceDeviceEncrypted = 16844037; // 0x1010505
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -1038,6 +1039,8 @@
     field public static final int popupBackground = 16843126; // 0x1010176
     field public static final int popupCharacters = 16843332; // 0x1010244
     field public static final int popupElevation = 16843916; // 0x101048c
+    field public static final int popupEnterTransition = 16844065; // 0x1010521
+    field public static final int popupExitTransition = 16844066; // 0x1010522
     field public static final int popupKeyboard = 16843331; // 0x1010243
     field public static final int popupLayout = 16843323; // 0x101023b
     field public static final int popupMenuStyle = 16843520; // 0x1010300
@@ -2855,14 +2858,10 @@
   }
 
   public final class GestureDescription {
-    method public static android.accessibilityservice.GestureDescription createClick(int, int);
-    method public static android.accessibilityservice.GestureDescription createLongClick(int, int);
-    method public static android.accessibilityservice.GestureDescription createPinch(int, int, int, int, float, long);
-    method public static android.accessibilityservice.GestureDescription createSwipe(int, int, int, int, long);
+    method public static long getMaxGestureDuration();
+    method public static int getMaxStrokeCount();
     method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(int);
     method public int getStrokeCount();
-    field public static final long MAX_GESTURE_DURATION_MS = 60000L; // 0xea60L
-    field public static final int MAX_STROKE_COUNT = 10; // 0xa
   }
 
   public static class GestureDescription.Builder {
@@ -3653,7 +3652,6 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
@@ -4350,7 +4348,6 @@
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5991,7 +5988,6 @@
     method public int getCurrentFailedPasswordAttempts();
     method public deprecated java.lang.String getDeviceInitializerApp();
     method public deprecated android.content.ComponentName getDeviceInitializerComponent();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwner();
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.lang.String getDeviceOwnerNameOnAnyUser();
@@ -6047,6 +6043,7 @@
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void notifyPendingSystemUpdate(long);
@@ -6057,8 +6054,8 @@
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException;
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
@@ -6071,7 +6068,6 @@
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -6104,6 +6100,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6198,6 +6195,27 @@
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6511,6 +6529,8 @@
     method public long getIntervalMillis();
     method public long getMaxExecutionDelayMillis();
     method public long getMinLatencyMillis();
+    method public static final long getMinimumFlex();
+    method public static final long getMinimumPeriod();
     method public int getNetworkType();
     method public android.content.ComponentName getService();
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
@@ -6524,8 +6544,6 @@
     field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
-    field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
-    field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6848,31 +6866,6 @@
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -8277,8 +8270,8 @@
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
     method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public abstract android.content.Context createCredentialEncryptedStorageContext();
-    method public abstract android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.Context createCredentialProtectedStorageContext();
+    method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
@@ -8323,8 +8316,6 @@
     method public abstract java.lang.String getPackageResourcePath();
     method public abstract android.content.res.Resources getResources();
     method public abstract android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
-    method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
-    method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
@@ -8336,11 +8327,11 @@
     method public abstract deprecated int getWallpaperDesiredMinimumHeight();
     method public abstract deprecated int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public abstract boolean isCredentialEncryptedStorage();
-    method public abstract boolean isDeviceEncryptedStorage();
+    method public abstract boolean isCredentialProtectedStorage();
+    method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public abstract boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public abstract boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
     method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -8484,8 +8475,8 @@
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public deprecated void clearWallpaper() throws java.io.IOException;
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createCredentialEncryptedStorageContext();
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createCredentialProtectedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -8537,10 +8528,10 @@
     method public deprecated int getWallpaperDesiredMinimumHeight();
     method public deprecated int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isCredentialEncryptedStorage();
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isCredentialProtectedStorage();
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9643,10 +9634,10 @@
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
     field public int compatibleWidthLimitDp;
-    field public java.lang.String credentialEncryptedDataDir;
+    field public java.lang.String credentialProtectedDataDir;
     field public java.lang.String dataDir;
     field public int descriptionRes;
-    field public java.lang.String deviceEncryptedDataDir;
+    field public java.lang.String deviceProtectedDataDir;
     field public boolean enabled;
     field public int flags;
     field public int largestWidthLimitDp;
@@ -9683,8 +9674,8 @@
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
+    field public boolean directBootAware;
     field public boolean enabled;
-    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9934,6 +9925,7 @@
     method public void setAppIcon(android.graphics.Bitmap);
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
+    method public void setDontKillApp(boolean);
     method public void setGrantedRuntimePermissions(java.lang.String[]);
     method public void setInstallLocation(int);
     method public void setOriginatingUid(int);
@@ -10220,11 +10212,10 @@
     field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
+    field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
-    field public static final int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -15283,24 +15274,25 @@
   }
 
   public final class ContextHubManager {
-    method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
+    method public int[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
     method public int[] getContextHubHandles();
     method public android.hardware.location.ContextHubInfo getContextHubInfo(int);
     method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
     method public int loadNanoApp(int, android.hardware.location.NanoApp);
-    method public int registerContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback);
-    method public int registerContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback, android.os.Handler);
+    method public int registerCallback(android.hardware.location.ContextHubManager.Callback);
+    method public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler);
     method public int sendMessage(int, int, android.hardware.location.ContextHubMessage);
     method public int unloadNanoApp(int);
-    method public int unregisterContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback);
+    method public int unregisterCallback(android.hardware.location.ContextHubManager.Callback);
     field public static final int ANY_HUB = -1; // 0xffffffff
     field public static final int MSG_DATA_SEND = 3; // 0x3
     field public static final int MSG_LOAD_NANO_APP = 1; // 0x1
     field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
   }
 
-  public abstract class ContextHubManager.ContextHubCallback {
-    ctor public ContextHubManager.ContextHubCallback();
+  public static abstract class ContextHubManager.Callback {
+    ctor protected ContextHubManager.Callback();
+    method public abstract void onMessageReceipt(int, int, android.hardware.location.ContextHubMessage);
   }
 
   public class ContextHubMessage {
@@ -20436,7 +20428,6 @@
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
-    method public boolean isPseudorangeRateCorrected();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
     field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -20454,9 +20445,6 @@
     field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssMeasurementsEvent implements android.os.Parcelable {
     ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
     method public int describeContents();
@@ -20475,9 +20463,6 @@
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GnssMeasurementsEvent.GnssMeasurementsStatus implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
@@ -20503,9 +20488,6 @@
     field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssNavigationMessageEvent implements android.os.Parcelable {
     ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
     method public int describeContents();
@@ -20523,9 +20505,6 @@
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GnssNavigationMessageEvent.GnssNavigationMessageStatus implements java.lang.annotation.Annotation {
-  }
-
   public abstract interface GnssNmeaListener {
     method public abstract void onNmeaReceived(long, java.lang.String);
   }
@@ -20549,9 +20528,6 @@
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
-  }
-
   public abstract class GnssStatusCallback {
     ctor public GnssStatusCallback();
     method public void onFirstFix(int);
@@ -24712,8 +24688,6 @@
     method public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, android.media.tv.TvInputManager.HardwareCallback, android.media.tv.TvInputInfo);
     method public void addBlockedRating(android.media.tv.TvContentRating);
     method public boolean captureFrame(java.lang.String, android.view.Surface, android.media.tv.TvStreamConfig);
-    method public void createRecordingSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler);
-    method public void createSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler);
     method public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(java.lang.String);
     method public java.util.List<android.media.tv.TvContentRating> getBlockedRatings();
     method public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList();
@@ -24765,39 +24739,6 @@
     method public abstract void onStreamConfigChanged(android.media.tv.TvStreamConfig[]);
   }
 
-  public static final class TvInputManager.Session {
-    method public void dispatchSurfaceChanged(int, int, int);
-    method public java.lang.String getSelectedTrack(int);
-    method public java.util.List<android.media.tv.TvTrackInfo> getTracks(int);
-    method public void release();
-    method public void selectTrack(int, java.lang.String);
-    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
-    method public void setCaptionEnabled(boolean);
-    method public void setStreamVolume(float);
-    method public void setSurface(android.view.Surface);
-    method public void tune(android.net.Uri);
-    method public void tune(android.net.Uri, android.os.Bundle);
-  }
-
-  public static abstract class TvInputManager.SessionCallback {
-    ctor public TvInputManager.SessionCallback();
-    method public void onChannelRetuned(android.media.tv.TvInputManager.Session, android.net.Uri);
-    method public void onContentAllowed(android.media.tv.TvInputManager.Session);
-    method public void onContentBlocked(android.media.tv.TvInputManager.Session, android.media.tv.TvContentRating);
-    method public void onLayoutSurface(android.media.tv.TvInputManager.Session, int, int, int, int);
-    method public void onSessionCreated(android.media.tv.TvInputManager.Session);
-    method public void onSessionEvent(android.media.tv.TvInputManager.Session, java.lang.String, android.os.Bundle);
-    method public void onSessionReleased(android.media.tv.TvInputManager.Session);
-    method public void onTimeShiftCurrentPositionChanged(android.media.tv.TvInputManager.Session, long);
-    method public void onTimeShiftStartPositionChanged(android.media.tv.TvInputManager.Session, long);
-    method public void onTimeShiftStatusChanged(android.media.tv.TvInputManager.Session, int);
-    method public void onTrackSelected(android.media.tv.TvInputManager.Session, int, java.lang.String);
-    method public void onTracksChanged(android.media.tv.TvInputManager.Session, java.util.List<android.media.tv.TvTrackInfo>);
-    method public void onVideoAvailable(android.media.tv.TvInputManager.Session);
-    method public void onVideoSizeChanged(android.media.tv.TvInputManager.Session, int, int);
-    method public void onVideoUnavailable(android.media.tv.TvInputManager.Session, int);
-  }
-
   public static abstract class TvInputManager.TvInputCallback {
     ctor public TvInputManager.TvInputCallback();
     method public void onInputAdded(java.lang.String);
@@ -25724,9 +25665,11 @@
 
   public class ScoredNetwork implements android.os.Parcelable {
     ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
+    ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+    field public final boolean meteredHint;
     field public final android.net.NetworkKey networkKey;
     field public final android.net.RssiCurve rssiCurve;
   }
@@ -31426,6 +31369,7 @@
     field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+    field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
     field public static final int USER_ACTIVITY_EVENT_TOUCH = 2; // 0x2
@@ -31718,10 +31662,6 @@
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
     method public boolean isUserUnlocked();
     method public boolean isUserUnlocked(android.os.UserHandle);
@@ -31952,6 +31892,7 @@
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
+    method public boolean isEncrypted(java.io.File);
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
@@ -32282,9 +32223,9 @@
     method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
-    method public void setStorageCredentialEncrypted();
+    method public void setStorageCredentialProtected();
     method public void setStorageDefault();
-    method public void setStorageDeviceEncrypted();
+    method public void setStorageDeviceProtected();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -39523,6 +39464,7 @@
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -40660,8 +40602,8 @@
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createCredentialEncryptedStorageContext();
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createCredentialProtectedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -40712,10 +40654,10 @@
     method public int getWallpaperDesiredMinimumHeight();
     method public int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isCredentialEncryptedStorage();
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isCredentialProtectedStorage();
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -45351,7 +45293,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public void onVisibilityAggregated(android.view.View, int);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -46449,7 +46391,7 @@
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -48703,18 +48645,18 @@
     ctor public WebViewFactory();
     method public static android.content.pm.PackageInfo getLoadedPackageInfo();
     method public static java.lang.String getWebViewPackageName();
-    method public static int loadWebViewNativeLibraryFromPackage(java.lang.String);
+    method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader);
     method public static void prepareWebViewInZygote();
     field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize";
     field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
     field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7
     field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4
+    field public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10; // 0xa
     field public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; // 0x6
     field public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; // 0x5
     field public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; // 0x3
-    field public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9; // 0x9
+    field public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 8; // 0x8
     field public static final int LIBLOAD_SUCCESS = 0; // 0x0
-    field public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8; // 0x8
     field public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1; // 0x1
   }
 
@@ -48853,7 +48795,9 @@
 
   public static abstract interface WebViewProvider.ViewDelegate {
     method public abstract boolean dispatchKeyEvent(android.view.KeyEvent);
+    method public abstract android.view.View findFocus(android.view.View);
     method public abstract android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
+    method public abstract android.os.Handler getHandler(android.os.Handler);
     method public abstract void onActivityResult(int, int, android.content.Intent);
     method public abstract void onAttachedToWindow();
     method public abstract void onConfigurationChanged(android.content.res.Configuration);
@@ -50299,6 +50243,8 @@
     method public android.graphics.drawable.Drawable getBackground();
     method public android.view.View getContentView();
     method public float getElevation();
+    method public android.transition.Transition getEnterTransition();
+    method public android.transition.Transition getExitTransition();
     method public int getHeight();
     method public int getInputMethodMode();
     method public int getMaxAvailableHeight(android.view.View);
@@ -53792,6 +53738,7 @@
     method public float floatValue();
     method public static int hashCode(double);
     method public int intValue();
+    method public static boolean isFinite(double);
     method public static boolean isInfinite(double);
     method public boolean isInfinite();
     method public static boolean isNaN(double);
@@ -53873,6 +53820,7 @@
     method public float floatValue();
     method public static float intBitsToFloat(int);
     method public int intValue();
+    method public static boolean isFinite(float);
     method public static boolean isInfinite(float);
     method public boolean isInfinite();
     method public static boolean isNaN(float);
@@ -60450,6 +60398,7 @@
     method public E get(int);
     method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
@@ -60551,6 +60500,10 @@
     method public static void parallelSort(T[], int, int);
     method public static void parallelSort(T[], java.util.Comparator<? super T>);
     method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static void setAll(int[], java.util.function.IntUnaryOperator);
+    method public static void setAll(long[], java.util.function.IntToLongFunction);
+    method public static void setAll(double[], java.util.function.IntToDoubleFunction);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -60577,6 +60530,14 @@
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[]);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
+    method public static java.util.stream.Stream<T> stream(T[]);
+    method public static java.util.stream.Stream<T> stream(T[], int, int);
+    method public static java.util.stream.IntStream stream(int[]);
+    method public static java.util.stream.IntStream stream(int[], int, int);
+    method public static java.util.stream.LongStream stream(long[]);
+    method public static java.util.stream.LongStream stream(long[], int, int);
+    method public static java.util.stream.DoubleStream stream(double[]);
+    method public static java.util.stream.DoubleStream stream(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -60736,11 +60697,13 @@
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Iterator<E> iterator();
+    method public default java.util.stream.Stream<E> parallelStream();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
     method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
+    method public default java.util.stream.Stream<E> stream();
     method public abstract java.lang.Object[] toArray();
     method public abstract T[] toArray(T[]);
   }
@@ -61940,6 +61903,34 @@
     method public java.util.Spliterator<T> trySplit();
   }
 
+  public final class SplittableRandom {
+    ctor public SplittableRandom(long);
+    ctor public SplittableRandom();
+    method public java.util.stream.DoubleStream doubles(long);
+    method public java.util.stream.DoubleStream doubles();
+    method public java.util.stream.DoubleStream doubles(long, double, double);
+    method public java.util.stream.DoubleStream doubles(double, double);
+    method public java.util.stream.IntStream ints(long);
+    method public java.util.stream.IntStream ints();
+    method public java.util.stream.IntStream ints(long, int, int);
+    method public java.util.stream.IntStream ints(int, int);
+    method public java.util.stream.LongStream longs(long);
+    method public java.util.stream.LongStream longs();
+    method public java.util.stream.LongStream longs(long, long, long);
+    method public java.util.stream.LongStream longs(long, long);
+    method public boolean nextBoolean();
+    method public double nextDouble();
+    method public double nextDouble(double);
+    method public double nextDouble(double, double);
+    method public int nextInt();
+    method public int nextInt(int);
+    method public int nextInt(int, int);
+    method public long nextLong();
+    method public long nextLong(long);
+    method public long nextLong(long, long);
+    method public java.util.SplittableRandom split();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -63123,6 +63114,18 @@
 
   public class ThreadLocalRandom extends java.util.Random {
     method public static java.util.concurrent.ThreadLocalRandom current();
+    method public java.util.stream.DoubleStream doubles(long);
+    method public java.util.stream.DoubleStream doubles();
+    method public java.util.stream.DoubleStream doubles(long, double, double);
+    method public java.util.stream.DoubleStream doubles(double, double);
+    method public java.util.stream.IntStream ints(long);
+    method public java.util.stream.IntStream ints();
+    method public java.util.stream.IntStream ints(long, int, int);
+    method public java.util.stream.IntStream ints(int, int);
+    method public java.util.stream.LongStream longs(long);
+    method public java.util.stream.LongStream longs();
+    method public java.util.stream.LongStream longs(long, long, long);
+    method public java.util.stream.LongStream longs(long, long);
     method public double nextDouble(double);
     method public double nextDouble(double, double);
     method public int nextInt(int, int);
@@ -64524,6 +64527,292 @@
 
 }
 
+package java.util.stream {
+
+  public abstract interface BaseStream implements java.lang.AutoCloseable {
+    method public abstract void close();
+    method public abstract boolean isParallel();
+    method public abstract java.util.Iterator<T> iterator();
+    method public abstract S onClose(java.lang.Runnable);
+    method public abstract S parallel();
+    method public abstract S sequential();
+    method public abstract java.util.Spliterator<T> spliterator();
+    method public abstract S unordered();
+  }
+
+  public abstract interface Collector {
+    method public abstract java.util.function.BiConsumer<A, T> accumulator();
+    method public abstract java.util.Set<java.util.stream.Collector.Characteristics> characteristics();
+    method public abstract java.util.function.BinaryOperator<A> combiner();
+    method public abstract java.util.function.Function<A, R> finisher();
+    method public static java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
+    method public static java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
+    method public abstract java.util.function.Supplier<A> supplier();
+  }
+
+  public static final class Collector.Characteristics extends java.lang.Enum {
+    method public static java.util.stream.Collector.Characteristics valueOf(java.lang.String);
+    method public static final java.util.stream.Collector.Characteristics[] values();
+    enum_constant public static final java.util.stream.Collector.Characteristics CONCURRENT;
+    enum_constant public static final java.util.stream.Collector.Characteristics IDENTITY_FINISH;
+    enum_constant public static final java.util.stream.Collector.Characteristics UNORDERED;
+  }
+
+  public final class Collectors {
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Long> counting();
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining();
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence);
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public static java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
+    method public static java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static java.util.stream.Collector<T, ?, java.util.List<T>> toList();
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
+  }
+
+  public abstract interface DoubleStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.DoublePredicate);
+    method public abstract boolean anyMatch(java.util.function.DoublePredicate);
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Double> boxed();
+    method public static java.util.stream.DoubleStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
+    method public abstract long count();
+    method public abstract java.util.stream.DoubleStream distinct();
+    method public static java.util.stream.DoubleStream empty();
+    method public abstract java.util.stream.DoubleStream filter(java.util.function.DoublePredicate);
+    method public abstract java.util.OptionalDouble findAny();
+    method public abstract java.util.OptionalDouble findFirst();
+    method public abstract java.util.stream.DoubleStream flatMap(java.util.function.DoubleFunction<? extends java.util.stream.DoubleStream>);
+    method public abstract void forEach(java.util.function.DoubleConsumer);
+    method public abstract void forEachOrdered(java.util.function.DoubleConsumer);
+    method public static java.util.stream.DoubleStream generate(java.util.function.DoubleSupplier);
+    method public static java.util.stream.DoubleStream iterate(double, java.util.function.DoubleUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfDouble iterator();
+    method public abstract java.util.stream.DoubleStream limit(long);
+    method public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
+    method public abstract java.util.OptionalDouble max();
+    method public abstract java.util.OptionalDouble min();
+    method public abstract boolean noneMatch(java.util.function.DoublePredicate);
+    method public static java.util.stream.DoubleStream of(double);
+    method public static java.util.stream.DoubleStream of(double...);
+    method public abstract java.util.stream.DoubleStream parallel();
+    method public abstract java.util.stream.DoubleStream peek(java.util.function.DoubleConsumer);
+    method public abstract double reduce(double, java.util.function.DoubleBinaryOperator);
+    method public abstract java.util.OptionalDouble reduce(java.util.function.DoubleBinaryOperator);
+    method public abstract java.util.stream.DoubleStream sequential();
+    method public abstract java.util.stream.DoubleStream skip(long);
+    method public abstract java.util.stream.DoubleStream sorted();
+    method public abstract java.util.Spliterator.OfDouble spliterator();
+    method public abstract double sum();
+    method public abstract java.util.DoubleSummaryStatistics summaryStatistics();
+    method public abstract double[] toArray();
+  }
+
+  public static abstract interface DoubleStream.Builder implements java.util.function.DoubleConsumer {
+    method public abstract void accept(double);
+    method public default java.util.stream.DoubleStream.Builder add(double);
+    method public abstract java.util.stream.DoubleStream build();
+  }
+
+  public abstract interface IntStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.IntPredicate);
+    method public abstract boolean anyMatch(java.util.function.IntPredicate);
+    method public abstract java.util.stream.DoubleStream asDoubleStream();
+    method public abstract java.util.stream.LongStream asLongStream();
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Integer> boxed();
+    method public static java.util.stream.IntStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
+    method public abstract long count();
+    method public abstract java.util.stream.IntStream distinct();
+    method public static java.util.stream.IntStream empty();
+    method public abstract java.util.stream.IntStream filter(java.util.function.IntPredicate);
+    method public abstract java.util.OptionalInt findAny();
+    method public abstract java.util.OptionalInt findFirst();
+    method public abstract java.util.stream.IntStream flatMap(java.util.function.IntFunction<? extends java.util.stream.IntStream>);
+    method public abstract void forEach(java.util.function.IntConsumer);
+    method public abstract void forEachOrdered(java.util.function.IntConsumer);
+    method public static java.util.stream.IntStream generate(java.util.function.IntSupplier);
+    method public static java.util.stream.IntStream iterate(int, java.util.function.IntUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfInt iterator();
+    method public abstract java.util.stream.IntStream limit(long);
+    method public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
+    method public abstract java.util.OptionalInt max();
+    method public abstract java.util.OptionalInt min();
+    method public abstract boolean noneMatch(java.util.function.IntPredicate);
+    method public static java.util.stream.IntStream of(int);
+    method public static java.util.stream.IntStream of(int...);
+    method public abstract java.util.stream.IntStream parallel();
+    method public abstract java.util.stream.IntStream peek(java.util.function.IntConsumer);
+    method public static java.util.stream.IntStream range(int, int);
+    method public static java.util.stream.IntStream rangeClosed(int, int);
+    method public abstract int reduce(int, java.util.function.IntBinaryOperator);
+    method public abstract java.util.OptionalInt reduce(java.util.function.IntBinaryOperator);
+    method public abstract java.util.stream.IntStream sequential();
+    method public abstract java.util.stream.IntStream skip(long);
+    method public abstract java.util.stream.IntStream sorted();
+    method public abstract java.util.Spliterator.OfInt spliterator();
+    method public abstract int sum();
+    method public abstract java.util.IntSummaryStatistics summaryStatistics();
+    method public abstract int[] toArray();
+  }
+
+  public static abstract interface IntStream.Builder implements java.util.function.IntConsumer {
+    method public abstract void accept(int);
+    method public default java.util.stream.IntStream.Builder add(int);
+    method public abstract java.util.stream.IntStream build();
+  }
+
+  public abstract interface LongStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.LongPredicate);
+    method public abstract boolean anyMatch(java.util.function.LongPredicate);
+    method public abstract java.util.stream.DoubleStream asDoubleStream();
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Long> boxed();
+    method public static java.util.stream.LongStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
+    method public abstract long count();
+    method public abstract java.util.stream.LongStream distinct();
+    method public static java.util.stream.LongStream empty();
+    method public abstract java.util.stream.LongStream filter(java.util.function.LongPredicate);
+    method public abstract java.util.OptionalLong findAny();
+    method public abstract java.util.OptionalLong findFirst();
+    method public abstract java.util.stream.LongStream flatMap(java.util.function.LongFunction<? extends java.util.stream.LongStream>);
+    method public abstract void forEach(java.util.function.LongConsumer);
+    method public abstract void forEachOrdered(java.util.function.LongConsumer);
+    method public static java.util.stream.LongStream generate(java.util.function.LongSupplier);
+    method public static java.util.stream.LongStream iterate(long, java.util.function.LongUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfLong iterator();
+    method public abstract java.util.stream.LongStream limit(long);
+    method public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
+    method public abstract java.util.OptionalLong max();
+    method public abstract java.util.OptionalLong min();
+    method public abstract boolean noneMatch(java.util.function.LongPredicate);
+    method public static java.util.stream.LongStream of(long);
+    method public static java.util.stream.LongStream of(long...);
+    method public abstract java.util.stream.LongStream parallel();
+    method public abstract java.util.stream.LongStream peek(java.util.function.LongConsumer);
+    method public static java.util.stream.LongStream range(long, long);
+    method public static java.util.stream.LongStream rangeClosed(long, long);
+    method public abstract long reduce(long, java.util.function.LongBinaryOperator);
+    method public abstract java.util.OptionalLong reduce(java.util.function.LongBinaryOperator);
+    method public abstract java.util.stream.LongStream sequential();
+    method public abstract java.util.stream.LongStream skip(long);
+    method public abstract java.util.stream.LongStream sorted();
+    method public abstract java.util.Spliterator.OfLong spliterator();
+    method public abstract long sum();
+    method public abstract java.util.LongSummaryStatistics summaryStatistics();
+    method public abstract long[] toArray();
+  }
+
+  public static abstract interface LongStream.Builder implements java.util.function.LongConsumer {
+    method public abstract void accept(long);
+    method public default java.util.stream.LongStream.Builder add(long);
+    method public abstract java.util.stream.LongStream build();
+  }
+
+  public abstract interface Stream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.Predicate<? super T>);
+    method public abstract boolean anyMatch(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Stream.Builder<T> builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
+    method public abstract R collect(java.util.stream.Collector<? super T, A, R>);
+    method public static java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
+    method public abstract long count();
+    method public abstract java.util.stream.Stream<T> distinct();
+    method public static java.util.stream.Stream<T> empty();
+    method public abstract java.util.stream.Stream<T> filter(java.util.function.Predicate<? super T>);
+    method public abstract java.util.Optional<T> findAny();
+    method public abstract java.util.Optional<T> findFirst();
+    method public abstract java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
+    method public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function<? super T, ? extends java.util.stream.DoubleStream>);
+    method public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function<? super T, ? extends java.util.stream.IntStream>);
+    method public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function<? super T, ? extends java.util.stream.LongStream>);
+    method public abstract void forEach(java.util.function.Consumer<? super T>);
+    method public abstract void forEachOrdered(java.util.function.Consumer<? super T>);
+    method public static java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
+    method public static java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
+    method public abstract java.util.stream.Stream<T> limit(long);
+    method public abstract java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction<? super T>);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction<? super T>);
+    method public abstract java.util.Optional<T> max(java.util.Comparator<? super T>);
+    method public abstract java.util.Optional<T> min(java.util.Comparator<? super T>);
+    method public abstract boolean noneMatch(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Stream<T> of(T);
+    method public static java.util.stream.Stream<T> of(T...);
+    method public abstract java.util.stream.Stream<T> peek(java.util.function.Consumer<? super T>);
+    method public abstract T reduce(T, java.util.function.BinaryOperator<T>);
+    method public abstract java.util.Optional<T> reduce(java.util.function.BinaryOperator<T>);
+    method public abstract U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
+    method public abstract java.util.stream.Stream<T> skip(long);
+    method public abstract java.util.stream.Stream<T> sorted();
+    method public abstract java.util.stream.Stream<T> sorted(java.util.Comparator<? super T>);
+    method public abstract java.lang.Object[] toArray();
+    method public abstract A[] toArray(java.util.function.IntFunction<A[]>);
+  }
+
+  public static abstract interface Stream.Builder implements java.util.function.Consumer {
+    method public abstract void accept(T);
+    method public default java.util.stream.Stream.Builder<T> add(T);
+    method public abstract java.util.stream.Stream<T> build();
+  }
+
+  public final class StreamSupport {
+    method public static java.util.stream.DoubleStream doubleStream(java.util.Spliterator.OfDouble, boolean);
+    method public static java.util.stream.DoubleStream doubleStream(java.util.function.Supplier<? extends java.util.Spliterator.OfDouble>, int, boolean);
+    method public static java.util.stream.IntStream intStream(java.util.Spliterator.OfInt, boolean);
+    method public static java.util.stream.IntStream intStream(java.util.function.Supplier<? extends java.util.Spliterator.OfInt>, int, boolean);
+    method public static java.util.stream.LongStream longStream(java.util.Spliterator.OfLong, boolean);
+    method public static java.util.stream.LongStream longStream(java.util.function.Supplier<? extends java.util.Spliterator.OfLong>, int, boolean);
+    method public static java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
+    method public static java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
+  }
+
+}
+
 package java.util.zip {
 
   public class Adler32 implements java.util.zip.Checksum {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index caeecf5..d48b9b3 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -15,12 +15,42 @@
 
 }
 
+package android.content {
+
+  public abstract class Context {
+    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
+    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
+    method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
+    method public deprecated boolean isCredentialEncryptedStorage();
+    method public deprecated boolean isDeviceEncryptedStorage();
+    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
+    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+  }
+
+}
+
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String credentialEncryptedDataDir;
+    field public deprecated java.lang.String deviceEncryptedDataDir;
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    field public deprecated boolean encryptionAware;
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public abstract class PackageManager {
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
+    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
+  }
+
 }
 
 package android.database {
@@ -96,6 +126,19 @@
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
+  }
+
+}
+
+package android.preference {
+
+  public class PreferenceManager {
+    method public deprecated void setStorageCredentialEncrypted();
+    method public deprecated void setStorageDeviceEncrypted();
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 2c7df1b..879f467 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -443,6 +443,7 @@
     field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
     field public static final int debuggable = 16842767; // 0x101000f
     field public static final int defaultHeight = 16844021; // 0x10104f5
+    field public static final int defaultToDeviceProtectedStorage = 16844037; // 0x1010505
     field public static final int defaultValue = 16843245; // 0x10101ed
     field public static final int defaultWidth = 16844020; // 0x10104f4
     field public static final int delay = 16843212; // 0x10101cc
@@ -462,6 +463,7 @@
     field public static final int dialogTheme = 16843528; // 0x1010308
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
+    field public static final int directBootAware = 16844038; // 0x1010506
     field public static final int direction = 16843217; // 0x10101d1
     field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
@@ -510,7 +512,6 @@
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
-    field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
     field public static final int endX = 16844051; // 0x1010513
@@ -559,6 +560,7 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -574,7 +576,6 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
-    field public static final int forceDeviceEncrypted = 16844037; // 0x1010505
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -943,6 +944,8 @@
     field public static final int popupBackground = 16843126; // 0x1010176
     field public static final int popupCharacters = 16843332; // 0x1010244
     field public static final int popupElevation = 16843916; // 0x101048c
+    field public static final int popupEnterTransition = 16844065; // 0x1010521
+    field public static final int popupExitTransition = 16844066; // 0x1010522
     field public static final int popupKeyboard = 16843331; // 0x1010243
     field public static final int popupLayout = 16843323; // 0x101023b
     field public static final int popupMenuStyle = 16843520; // 0x1010300
@@ -2753,14 +2756,10 @@
   }
 
   public final class GestureDescription {
-    method public static android.accessibilityservice.GestureDescription createClick(int, int);
-    method public static android.accessibilityservice.GestureDescription createLongClick(int, int);
-    method public static android.accessibilityservice.GestureDescription createPinch(int, int, int, int, float, long);
-    method public static android.accessibilityservice.GestureDescription createSwipe(int, int, int, int, long);
+    method public static long getMaxGestureDuration();
+    method public static int getMaxStrokeCount();
     method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(int);
     method public int getStrokeCount();
-    field public static final long MAX_GESTURE_DURATION_MS = 60000L; // 0xea60L
-    field public static final int MAX_STROKE_COUNT = 10; // 0xa
   }
 
   public static class GestureDescription.Builder {
@@ -3536,7 +3535,6 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
@@ -4218,7 +4216,6 @@
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5856,7 +5853,6 @@
     method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5905,6 +5901,7 @@
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void reboot(android.content.ComponentName);
@@ -5914,8 +5911,8 @@
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5927,7 +5924,6 @@
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -5960,6 +5956,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6045,6 +6042,27 @@
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6249,6 +6267,8 @@
     method public long getIntervalMillis();
     method public long getMaxExecutionDelayMillis();
     method public long getMinLatencyMillis();
+    method public static final long getMinimumFlex();
+    method public static final long getMinimumPeriod();
     method public int getNetworkType();
     method public android.content.ComponentName getService();
     method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
@@ -6262,8 +6282,6 @@
     field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
-    field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
-    field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6585,31 +6603,6 @@
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -7984,7 +7977,7 @@
     method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public abstract deprecated void clearWallpaper() throws java.io.IOException;
     method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public abstract android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.Context createDeviceProtectedStorageContext();
     method public abstract android.content.Context createDisplayContext(android.view.Display);
     method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] databaseList();
@@ -8029,8 +8022,6 @@
     method public abstract java.lang.String getPackageResourcePath();
     method public abstract android.content.res.Resources getResources();
     method public abstract android.content.SharedPreferences getSharedPreferences(java.lang.String, int);
-    method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
-    method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
     method public final java.lang.String getString(int);
     method public final java.lang.String getString(int, java.lang.Object...);
     method public abstract java.lang.Object getSystemService(java.lang.String);
@@ -8043,10 +8034,10 @@
     method public abstract deprecated int getWallpaperDesiredMinimumHeight();
     method public abstract deprecated int getWallpaperDesiredMinimumWidth();
     method public abstract void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public abstract boolean isDeviceEncryptedStorage();
+    method public abstract boolean isDeviceProtectedStorage();
     method public boolean isRestricted();
-    method public abstract boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public abstract boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public abstract boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public final android.content.res.TypedArray obtainStyledAttributes(int[]);
     method public final android.content.res.TypedArray obtainStyledAttributes(int, int[]) throws android.content.res.Resources.NotFoundException;
     method public final android.content.res.TypedArray obtainStyledAttributes(android.util.AttributeSet, int[]);
@@ -8181,7 +8172,7 @@
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public deprecated void clearWallpaper() throws java.io.IOException;
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -8234,9 +8225,9 @@
     method public deprecated int getWallpaperDesiredMinimumHeight();
     method public deprecated int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -9329,10 +9320,9 @@
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
     field public int compatibleWidthLimitDp;
-    field public java.lang.String credentialEncryptedDataDir;
     field public java.lang.String dataDir;
     field public int descriptionRes;
-    field public java.lang.String deviceEncryptedDataDir;
+    field public java.lang.String deviceProtectedDataDir;
     field public boolean enabled;
     field public int flags;
     field public int largestWidthLimitDp;
@@ -9369,8 +9359,8 @@
     method public boolean isEnabled();
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
+    field public boolean directBootAware;
     field public boolean enabled;
-    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9842,11 +9832,10 @@
     field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
     field public static final int MATCH_ALL = 131072; // 0x20000
     field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
+    field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
+    field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
-    field public static final int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
-    field public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
-    field public static final int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
     field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000
     field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000
     field public static final long MAXIMUM_VERIFICATION_TIMEOUT = 3600000L; // 0x36ee80L
@@ -19297,7 +19286,6 @@
     method public boolean hasCarrierPhase();
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
-    method public boolean isPseudorangeRateCorrected();
     method public void reset();
     method public void resetCarrierCycles();
     method public void resetCarrierFrequencyHz();
@@ -19315,7 +19303,6 @@
     method public void setCn0DbHz(double);
     method public void setConstellationType(int);
     method public void setMultipathIndicator(int);
-    method public void setPseudorangeRateCorrected(boolean);
     method public void setPseudorangeRateMetersPerSecond(double);
     method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
     method public void setReceivedSvTimeNanos(long);
@@ -19341,9 +19328,6 @@
     field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssMeasurementsEvent implements android.os.Parcelable {
     ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
     method public int describeContents();
@@ -19362,9 +19346,6 @@
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GnssMeasurementsEvent.GnssMeasurementsStatus implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssNavigationMessage implements android.os.Parcelable {
     ctor public GnssNavigationMessage();
     method public int describeContents();
@@ -19399,9 +19380,6 @@
     field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
-  }
-
   public final class GnssNavigationMessageEvent implements android.os.Parcelable {
     ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
     method public int describeContents();
@@ -19419,9 +19397,6 @@
     method public void onStatusChanged(int);
   }
 
-  public static abstract class GnssNavigationMessageEvent.GnssNavigationMessageStatus implements java.lang.annotation.Annotation {
-  }
-
   public abstract interface GnssNmeaListener {
     method public abstract void onNmeaReceived(long, java.lang.String);
   }
@@ -19445,9 +19420,6 @@
     field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
   }
 
-  public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
-  }
-
   public abstract class GnssStatusCallback {
     ctor public GnssStatusCallback();
     method public void onFirstFix(int);
@@ -23156,6 +23128,7 @@
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
     method public void notifyTuned(android.net.Uri);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
     method public abstract void onStopRecording();
@@ -23173,6 +23146,7 @@
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyVideoAvailable();
     method public void notifyVideoUnavailable(int);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -23204,6 +23178,7 @@
   public class TvRecordingClient {
     ctor public TvRecordingClient(android.content.Context, java.lang.String, android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
     method public void release();
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void startRecording(android.net.Uri);
     method public void stopRecording();
     method public void tune(java.lang.String, android.net.Uri);
@@ -23265,6 +23240,7 @@
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void setCallback(android.media.tv.TvView.TvInputCallback);
     method public void setCaptionEnabled(boolean);
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
@@ -29439,10 +29415,6 @@
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndLocked();
-    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public deprecated boolean isUserRunningAndUnlocked();
-    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
     method public boolean isUserUnlocked();
     method public boolean isUserUnlocked(android.os.UserHandle);
@@ -29673,6 +29645,7 @@
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
+    method public boolean isEncrypted(java.io.File);
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
@@ -30004,7 +29977,7 @@
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
     method public void setStorageDefault();
-    method public void setStorageDeviceEncrypted();
+    method public void setStorageDeviceProtected();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -36901,6 +36874,7 @@
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -37985,7 +37959,7 @@
     method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
     method public void clearWallpaper();
     method public android.content.Context createConfigurationContext(android.content.res.Configuration);
-    method public android.content.Context createDeviceEncryptedStorageContext();
+    method public android.content.Context createDeviceProtectedStorageContext();
     method public android.content.Context createDisplayContext(android.view.Display);
     method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] databaseList();
@@ -38037,9 +38011,9 @@
     method public int getWallpaperDesiredMinimumHeight();
     method public int getWallpaperDesiredMinimumWidth();
     method public void grantUriPermission(java.lang.String, android.net.Uri, int);
-    method public boolean isDeviceEncryptedStorage();
-    method public boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
-    method public boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+    method public boolean isDeviceProtectedStorage();
+    method public boolean moveDatabaseFrom(android.content.Context, java.lang.String);
+    method public boolean moveSharedPreferencesFrom(android.content.Context, java.lang.String);
     method public java.io.FileInputStream openFileInput(java.lang.String) throws java.io.FileNotFoundException;
     method public java.io.FileOutputStream openFileOutput(java.lang.String, int) throws java.io.FileNotFoundException;
     method public android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase.CursorFactory);
@@ -42667,7 +42641,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
-    method public void onVisibilityAggregated(android.view.View, int);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -43764,7 +43738,7 @@
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -47278,6 +47252,8 @@
     method public android.graphics.drawable.Drawable getBackground();
     method public android.view.View getContentView();
     method public float getElevation();
+    method public android.transition.Transition getEnterTransition();
+    method public android.transition.Transition getExitTransition();
     method public int getHeight();
     method public int getInputMethodMode();
     method public int getMaxAvailableHeight(android.view.View);
@@ -50771,6 +50747,7 @@
     method public float floatValue();
     method public static int hashCode(double);
     method public int intValue();
+    method public static boolean isFinite(double);
     method public static boolean isInfinite(double);
     method public boolean isInfinite();
     method public static boolean isNaN(double);
@@ -50852,6 +50829,7 @@
     method public float floatValue();
     method public static float intBitsToFloat(int);
     method public int intValue();
+    method public static boolean isFinite(float);
     method public static boolean isInfinite(float);
     method public boolean isInfinite();
     method public static boolean isNaN(float);
@@ -57429,6 +57407,7 @@
     method public E get(int);
     method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
@@ -57530,6 +57509,10 @@
     method public static void parallelSort(T[], int, int);
     method public static void parallelSort(T[], java.util.Comparator<? super T>);
     method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
+    method public static void setAll(T[], java.util.function.IntFunction<? extends T>);
+    method public static void setAll(int[], java.util.function.IntUnaryOperator);
+    method public static void setAll(long[], java.util.function.IntToLongFunction);
+    method public static void setAll(double[], java.util.function.IntToDoubleFunction);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -57556,6 +57539,14 @@
     method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
     method public static java.util.Spliterator.OfDouble spliterator(double[]);
     method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
+    method public static java.util.stream.Stream<T> stream(T[]);
+    method public static java.util.stream.Stream<T> stream(T[], int, int);
+    method public static java.util.stream.IntStream stream(int[]);
+    method public static java.util.stream.IntStream stream(int[], int, int);
+    method public static java.util.stream.LongStream stream(long[]);
+    method public static java.util.stream.LongStream stream(long[], int, int);
+    method public static java.util.stream.DoubleStream stream(double[]);
+    method public static java.util.stream.DoubleStream stream(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -57715,11 +57706,13 @@
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Iterator<E> iterator();
+    method public default java.util.stream.Stream<E> parallelStream();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
     method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
+    method public default java.util.stream.Stream<E> stream();
     method public abstract java.lang.Object[] toArray();
     method public abstract T[] toArray(T[]);
   }
@@ -58919,6 +58912,34 @@
     method public java.util.Spliterator<T> trySplit();
   }
 
+  public final class SplittableRandom {
+    ctor public SplittableRandom(long);
+    ctor public SplittableRandom();
+    method public java.util.stream.DoubleStream doubles(long);
+    method public java.util.stream.DoubleStream doubles();
+    method public java.util.stream.DoubleStream doubles(long, double, double);
+    method public java.util.stream.DoubleStream doubles(double, double);
+    method public java.util.stream.IntStream ints(long);
+    method public java.util.stream.IntStream ints();
+    method public java.util.stream.IntStream ints(long, int, int);
+    method public java.util.stream.IntStream ints(int, int);
+    method public java.util.stream.LongStream longs(long);
+    method public java.util.stream.LongStream longs();
+    method public java.util.stream.LongStream longs(long, long, long);
+    method public java.util.stream.LongStream longs(long, long);
+    method public boolean nextBoolean();
+    method public double nextDouble();
+    method public double nextDouble(double);
+    method public double nextDouble(double, double);
+    method public int nextInt();
+    method public int nextInt(int);
+    method public int nextInt(int, int);
+    method public long nextLong();
+    method public long nextLong(long);
+    method public long nextLong(long, long);
+    method public java.util.SplittableRandom split();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -60102,6 +60123,18 @@
 
   public class ThreadLocalRandom extends java.util.Random {
     method public static java.util.concurrent.ThreadLocalRandom current();
+    method public java.util.stream.DoubleStream doubles(long);
+    method public java.util.stream.DoubleStream doubles();
+    method public java.util.stream.DoubleStream doubles(long, double, double);
+    method public java.util.stream.DoubleStream doubles(double, double);
+    method public java.util.stream.IntStream ints(long);
+    method public java.util.stream.IntStream ints();
+    method public java.util.stream.IntStream ints(long, int, int);
+    method public java.util.stream.IntStream ints(int, int);
+    method public java.util.stream.LongStream longs(long);
+    method public java.util.stream.LongStream longs();
+    method public java.util.stream.LongStream longs(long, long, long);
+    method public java.util.stream.LongStream longs(long, long);
     method public double nextDouble(double);
     method public double nextDouble(double, double);
     method public int nextInt(int, int);
@@ -61503,6 +61536,292 @@
 
 }
 
+package java.util.stream {
+
+  public abstract interface BaseStream implements java.lang.AutoCloseable {
+    method public abstract void close();
+    method public abstract boolean isParallel();
+    method public abstract java.util.Iterator<T> iterator();
+    method public abstract S onClose(java.lang.Runnable);
+    method public abstract S parallel();
+    method public abstract S sequential();
+    method public abstract java.util.Spliterator<T> spliterator();
+    method public abstract S unordered();
+  }
+
+  public abstract interface Collector {
+    method public abstract java.util.function.BiConsumer<A, T> accumulator();
+    method public abstract java.util.Set<java.util.stream.Collector.Characteristics> characteristics();
+    method public abstract java.util.function.BinaryOperator<A> combiner();
+    method public abstract java.util.function.Function<A, R> finisher();
+    method public static java.util.stream.Collector<T, R, R> of(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, T>, java.util.function.BinaryOperator<R>, java.util.stream.Collector.Characteristics...);
+    method public static java.util.stream.Collector<T, A, R> of(java.util.function.Supplier<A>, java.util.function.BiConsumer<A, T>, java.util.function.BinaryOperator<A>, java.util.function.Function<A, R>, java.util.stream.Collector.Characteristics...);
+    method public abstract java.util.function.Supplier<A> supplier();
+  }
+
+  public static final class Collector.Characteristics extends java.lang.Enum {
+    method public static java.util.stream.Collector.Characteristics valueOf(java.lang.String);
+    method public static final java.util.stream.Collector.Characteristics[] values();
+    enum_constant public static final java.util.stream.Collector.Characteristics CONCURRENT;
+    enum_constant public static final java.util.stream.Collector.Characteristics IDENTITY_FINISH;
+    enum_constant public static final java.util.stream.Collector.Characteristics UNORDERED;
+  }
+
+  public final class Collectors {
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, A, RR> collectingAndThen(java.util.stream.Collector<T, A, R>, java.util.function.Function<R, RR>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Long> counting();
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>> groupingBy(java.util.function.Function<? super T, ? extends K>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, D>> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, M> groupingBy(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, M> groupingByConcurrent(java.util.function.Function<? super T, ? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining();
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence);
+    method public static java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String> joining(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public static java.util.stream.Collector<T, ?, R> mapping(java.util.function.Function<? super T, ? extends U>, java.util.stream.Collector<? super U, A, R>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> maxBy(java.util.Comparator<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> minBy(java.util.Comparator<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>> partitioningBy(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>> partitioningBy(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T, A, D>);
+    method public static java.util.stream.Collector<T, ?, T> reducing(T, java.util.function.BinaryOperator<T>);
+    method public static java.util.stream.Collector<T, ?, java.util.Optional<T>> reducing(java.util.function.BinaryOperator<T>);
+    method public static java.util.stream.Collector<T, ?, U> reducing(U, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics> summarizingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics> summarizingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics> summarizingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Double> summingDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Integer> summingInt(java.util.function.ToIntFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, java.lang.Long> summingLong(java.util.function.ToLongFunction<? super T>);
+    method public static java.util.stream.Collector<T, ?, C> toCollection(java.util.function.Supplier<C>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, M> toConcurrentMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static java.util.stream.Collector<T, ?, java.util.List<T>> toList();
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.stream.Collector<T, ?, java.util.Map<K, U>> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>);
+    method public static java.util.stream.Collector<T, ?, M> toMap(java.util.function.Function<? super T, ? extends K>, java.util.function.Function<? super T, ? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
+    method public static java.util.stream.Collector<T, ?, java.util.Set<T>> toSet();
+  }
+
+  public abstract interface DoubleStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.DoublePredicate);
+    method public abstract boolean anyMatch(java.util.function.DoublePredicate);
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Double> boxed();
+    method public static java.util.stream.DoubleStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjDoubleConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.DoubleStream concat(java.util.stream.DoubleStream, java.util.stream.DoubleStream);
+    method public abstract long count();
+    method public abstract java.util.stream.DoubleStream distinct();
+    method public static java.util.stream.DoubleStream empty();
+    method public abstract java.util.stream.DoubleStream filter(java.util.function.DoublePredicate);
+    method public abstract java.util.OptionalDouble findAny();
+    method public abstract java.util.OptionalDouble findFirst();
+    method public abstract java.util.stream.DoubleStream flatMap(java.util.function.DoubleFunction<? extends java.util.stream.DoubleStream>);
+    method public abstract void forEach(java.util.function.DoubleConsumer);
+    method public abstract void forEachOrdered(java.util.function.DoubleConsumer);
+    method public static java.util.stream.DoubleStream generate(java.util.function.DoubleSupplier);
+    method public static java.util.stream.DoubleStream iterate(double, java.util.function.DoubleUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfDouble iterator();
+    method public abstract java.util.stream.DoubleStream limit(long);
+    method public abstract java.util.stream.DoubleStream map(java.util.function.DoubleUnaryOperator);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.DoubleToIntFunction);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.DoubleToLongFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.DoubleFunction<? extends U>);
+    method public abstract java.util.OptionalDouble max();
+    method public abstract java.util.OptionalDouble min();
+    method public abstract boolean noneMatch(java.util.function.DoublePredicate);
+    method public static java.util.stream.DoubleStream of(double);
+    method public static java.util.stream.DoubleStream of(double...);
+    method public abstract java.util.stream.DoubleStream parallel();
+    method public abstract java.util.stream.DoubleStream peek(java.util.function.DoubleConsumer);
+    method public abstract double reduce(double, java.util.function.DoubleBinaryOperator);
+    method public abstract java.util.OptionalDouble reduce(java.util.function.DoubleBinaryOperator);
+    method public abstract java.util.stream.DoubleStream sequential();
+    method public abstract java.util.stream.DoubleStream skip(long);
+    method public abstract java.util.stream.DoubleStream sorted();
+    method public abstract java.util.Spliterator.OfDouble spliterator();
+    method public abstract double sum();
+    method public abstract java.util.DoubleSummaryStatistics summaryStatistics();
+    method public abstract double[] toArray();
+  }
+
+  public static abstract interface DoubleStream.Builder implements java.util.function.DoubleConsumer {
+    method public abstract void accept(double);
+    method public default java.util.stream.DoubleStream.Builder add(double);
+    method public abstract java.util.stream.DoubleStream build();
+  }
+
+  public abstract interface IntStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.IntPredicate);
+    method public abstract boolean anyMatch(java.util.function.IntPredicate);
+    method public abstract java.util.stream.DoubleStream asDoubleStream();
+    method public abstract java.util.stream.LongStream asLongStream();
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Integer> boxed();
+    method public static java.util.stream.IntStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjIntConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.IntStream concat(java.util.stream.IntStream, java.util.stream.IntStream);
+    method public abstract long count();
+    method public abstract java.util.stream.IntStream distinct();
+    method public static java.util.stream.IntStream empty();
+    method public abstract java.util.stream.IntStream filter(java.util.function.IntPredicate);
+    method public abstract java.util.OptionalInt findAny();
+    method public abstract java.util.OptionalInt findFirst();
+    method public abstract java.util.stream.IntStream flatMap(java.util.function.IntFunction<? extends java.util.stream.IntStream>);
+    method public abstract void forEach(java.util.function.IntConsumer);
+    method public abstract void forEachOrdered(java.util.function.IntConsumer);
+    method public static java.util.stream.IntStream generate(java.util.function.IntSupplier);
+    method public static java.util.stream.IntStream iterate(int, java.util.function.IntUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfInt iterator();
+    method public abstract java.util.stream.IntStream limit(long);
+    method public abstract java.util.stream.IntStream map(java.util.function.IntUnaryOperator);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.IntToDoubleFunction);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.IntToLongFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.IntFunction<? extends U>);
+    method public abstract java.util.OptionalInt max();
+    method public abstract java.util.OptionalInt min();
+    method public abstract boolean noneMatch(java.util.function.IntPredicate);
+    method public static java.util.stream.IntStream of(int);
+    method public static java.util.stream.IntStream of(int...);
+    method public abstract java.util.stream.IntStream parallel();
+    method public abstract java.util.stream.IntStream peek(java.util.function.IntConsumer);
+    method public static java.util.stream.IntStream range(int, int);
+    method public static java.util.stream.IntStream rangeClosed(int, int);
+    method public abstract int reduce(int, java.util.function.IntBinaryOperator);
+    method public abstract java.util.OptionalInt reduce(java.util.function.IntBinaryOperator);
+    method public abstract java.util.stream.IntStream sequential();
+    method public abstract java.util.stream.IntStream skip(long);
+    method public abstract java.util.stream.IntStream sorted();
+    method public abstract java.util.Spliterator.OfInt spliterator();
+    method public abstract int sum();
+    method public abstract java.util.IntSummaryStatistics summaryStatistics();
+    method public abstract int[] toArray();
+  }
+
+  public static abstract interface IntStream.Builder implements java.util.function.IntConsumer {
+    method public abstract void accept(int);
+    method public default java.util.stream.IntStream.Builder add(int);
+    method public abstract java.util.stream.IntStream build();
+  }
+
+  public abstract interface LongStream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.LongPredicate);
+    method public abstract boolean anyMatch(java.util.function.LongPredicate);
+    method public abstract java.util.stream.DoubleStream asDoubleStream();
+    method public abstract java.util.OptionalDouble average();
+    method public abstract java.util.stream.Stream<java.lang.Long> boxed();
+    method public static java.util.stream.LongStream.Builder builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.ObjLongConsumer<R>, java.util.function.BiConsumer<R, R>);
+    method public static java.util.stream.LongStream concat(java.util.stream.LongStream, java.util.stream.LongStream);
+    method public abstract long count();
+    method public abstract java.util.stream.LongStream distinct();
+    method public static java.util.stream.LongStream empty();
+    method public abstract java.util.stream.LongStream filter(java.util.function.LongPredicate);
+    method public abstract java.util.OptionalLong findAny();
+    method public abstract java.util.OptionalLong findFirst();
+    method public abstract java.util.stream.LongStream flatMap(java.util.function.LongFunction<? extends java.util.stream.LongStream>);
+    method public abstract void forEach(java.util.function.LongConsumer);
+    method public abstract void forEachOrdered(java.util.function.LongConsumer);
+    method public static java.util.stream.LongStream generate(java.util.function.LongSupplier);
+    method public static java.util.stream.LongStream iterate(long, java.util.function.LongUnaryOperator);
+    method public abstract java.util.PrimitiveIterator.OfLong iterator();
+    method public abstract java.util.stream.LongStream limit(long);
+    method public abstract java.util.stream.LongStream map(java.util.function.LongUnaryOperator);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.LongToDoubleFunction);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.LongToIntFunction);
+    method public abstract java.util.stream.Stream<U> mapToObj(java.util.function.LongFunction<? extends U>);
+    method public abstract java.util.OptionalLong max();
+    method public abstract java.util.OptionalLong min();
+    method public abstract boolean noneMatch(java.util.function.LongPredicate);
+    method public static java.util.stream.LongStream of(long);
+    method public static java.util.stream.LongStream of(long...);
+    method public abstract java.util.stream.LongStream parallel();
+    method public abstract java.util.stream.LongStream peek(java.util.function.LongConsumer);
+    method public static java.util.stream.LongStream range(long, long);
+    method public static java.util.stream.LongStream rangeClosed(long, long);
+    method public abstract long reduce(long, java.util.function.LongBinaryOperator);
+    method public abstract java.util.OptionalLong reduce(java.util.function.LongBinaryOperator);
+    method public abstract java.util.stream.LongStream sequential();
+    method public abstract java.util.stream.LongStream skip(long);
+    method public abstract java.util.stream.LongStream sorted();
+    method public abstract java.util.Spliterator.OfLong spliterator();
+    method public abstract long sum();
+    method public abstract java.util.LongSummaryStatistics summaryStatistics();
+    method public abstract long[] toArray();
+  }
+
+  public static abstract interface LongStream.Builder implements java.util.function.LongConsumer {
+    method public abstract void accept(long);
+    method public default java.util.stream.LongStream.Builder add(long);
+    method public abstract java.util.stream.LongStream build();
+  }
+
+  public abstract interface Stream implements java.util.stream.BaseStream {
+    method public abstract boolean allMatch(java.util.function.Predicate<? super T>);
+    method public abstract boolean anyMatch(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Stream.Builder<T> builder();
+    method public abstract R collect(java.util.function.Supplier<R>, java.util.function.BiConsumer<R, ? super T>, java.util.function.BiConsumer<R, R>);
+    method public abstract R collect(java.util.stream.Collector<? super T, A, R>);
+    method public static java.util.stream.Stream<T> concat(java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>);
+    method public abstract long count();
+    method public abstract java.util.stream.Stream<T> distinct();
+    method public static java.util.stream.Stream<T> empty();
+    method public abstract java.util.stream.Stream<T> filter(java.util.function.Predicate<? super T>);
+    method public abstract java.util.Optional<T> findAny();
+    method public abstract java.util.Optional<T> findFirst();
+    method public abstract java.util.stream.Stream<R> flatMap(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends R>>);
+    method public abstract java.util.stream.DoubleStream flatMapToDouble(java.util.function.Function<? super T, ? extends java.util.stream.DoubleStream>);
+    method public abstract java.util.stream.IntStream flatMapToInt(java.util.function.Function<? super T, ? extends java.util.stream.IntStream>);
+    method public abstract java.util.stream.LongStream flatMapToLong(java.util.function.Function<? super T, ? extends java.util.stream.LongStream>);
+    method public abstract void forEach(java.util.function.Consumer<? super T>);
+    method public abstract void forEachOrdered(java.util.function.Consumer<? super T>);
+    method public static java.util.stream.Stream<T> generate(java.util.function.Supplier<T>);
+    method public static java.util.stream.Stream<T> iterate(T, java.util.function.UnaryOperator<T>);
+    method public abstract java.util.stream.Stream<T> limit(long);
+    method public abstract java.util.stream.Stream<R> map(java.util.function.Function<? super T, ? extends R>);
+    method public abstract java.util.stream.DoubleStream mapToDouble(java.util.function.ToDoubleFunction<? super T>);
+    method public abstract java.util.stream.IntStream mapToInt(java.util.function.ToIntFunction<? super T>);
+    method public abstract java.util.stream.LongStream mapToLong(java.util.function.ToLongFunction<? super T>);
+    method public abstract java.util.Optional<T> max(java.util.Comparator<? super T>);
+    method public abstract java.util.Optional<T> min(java.util.Comparator<? super T>);
+    method public abstract boolean noneMatch(java.util.function.Predicate<? super T>);
+    method public static java.util.stream.Stream<T> of(T);
+    method public static java.util.stream.Stream<T> of(T...);
+    method public abstract java.util.stream.Stream<T> peek(java.util.function.Consumer<? super T>);
+    method public abstract T reduce(T, java.util.function.BinaryOperator<T>);
+    method public abstract java.util.Optional<T> reduce(java.util.function.BinaryOperator<T>);
+    method public abstract U reduce(U, java.util.function.BiFunction<U, ? super T, U>, java.util.function.BinaryOperator<U>);
+    method public abstract java.util.stream.Stream<T> skip(long);
+    method public abstract java.util.stream.Stream<T> sorted();
+    method public abstract java.util.stream.Stream<T> sorted(java.util.Comparator<? super T>);
+    method public abstract java.lang.Object[] toArray();
+    method public abstract A[] toArray(java.util.function.IntFunction<A[]>);
+  }
+
+  public static abstract interface Stream.Builder implements java.util.function.Consumer {
+    method public abstract void accept(T);
+    method public default java.util.stream.Stream.Builder<T> add(T);
+    method public abstract java.util.stream.Stream<T> build();
+  }
+
+  public final class StreamSupport {
+    method public static java.util.stream.DoubleStream doubleStream(java.util.Spliterator.OfDouble, boolean);
+    method public static java.util.stream.DoubleStream doubleStream(java.util.function.Supplier<? extends java.util.Spliterator.OfDouble>, int, boolean);
+    method public static java.util.stream.IntStream intStream(java.util.Spliterator.OfInt, boolean);
+    method public static java.util.stream.IntStream intStream(java.util.function.Supplier<? extends java.util.Spliterator.OfInt>, int, boolean);
+    method public static java.util.stream.LongStream longStream(java.util.Spliterator.OfLong, boolean);
+    method public static java.util.stream.LongStream longStream(java.util.function.Supplier<? extends java.util.Spliterator.OfLong>, int, boolean);
+    method public static java.util.stream.Stream<T> stream(java.util.Spliterator<T>, boolean);
+    method public static java.util.stream.Stream<T> stream(java.util.function.Supplier<? extends java.util.Spliterator<T>>, int, boolean);
+  }
+
+}
+
 package java.util.zip {
 
   public class Adler32 implements java.util.zip.Checksum {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 8ac2d63..36c8ce5 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -17,12 +17,42 @@
 
 }
 
+package android.content {
+
+  public abstract class Context {
+    method public deprecated android.content.Context createCredentialEncryptedStorageContext();
+    method public deprecated android.content.Context createDeviceEncryptedStorageContext();
+    method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
+    method public abstract java.io.File getSharedPreferencesPath(java.lang.String);
+    method public deprecated boolean isCredentialEncryptedStorage();
+    method public deprecated boolean isDeviceEncryptedStorage();
+    method public deprecated boolean migrateDatabaseFrom(android.content.Context, java.lang.String);
+    method public deprecated boolean migrateSharedPreferencesFrom(android.content.Context, java.lang.String);
+  }
+
+}
+
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String credentialEncryptedDataDir;
+    field public deprecated java.lang.String deviceEncryptedDataDir;
+  }
+
+  public class ComponentInfo extends android.content.pm.PackageItemInfo {
+    field public deprecated boolean encryptionAware;
+  }
+
   public class PackageInfo implements android.os.Parcelable {
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public abstract class PackageManager {
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE = 524288; // 0x80000
+    field public static final deprecated int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = 786432; // 0xc0000
+    field public static final deprecated int MATCH_ENCRYPTION_UNAWARE = 262144; // 0x40000
+  }
+
 }
 
 package android.database {
@@ -98,6 +128,19 @@
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
     method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
+  }
+
+}
+
+package android.preference {
+
+  public class PreferenceManager {
+    method public deprecated void setStorageCredentialEncrypted();
+    method public deprecated void setStorageDeviceEncrypted();
   }
 
 }
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 8bcbf51..7590325 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -305,7 +305,7 @@
     }
 
     if (zygote) {
-        PreloadPublicNativeLibraries();
+        InitializeNativeLoader();
         runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
     } else if (className) {
         runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index ac3b8e3..ddc5b0c 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -851,6 +851,7 @@
                     return connection.getMagnificationScale();
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to obtain scale", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return 1.0f;
@@ -879,6 +880,7 @@
                     return connection.getMagnificationCenterX();
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to obtain center X", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return 0.0f;
@@ -907,6 +909,7 @@
                     return connection.getMagnificationCenterY();
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to obtain center Y", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return 0.0f;
@@ -933,6 +936,7 @@
                     return connection.getMagnifiedRegion();
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to obtain magnified region", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return Region.obtain();
@@ -961,6 +965,7 @@
                     return connection.resetMagnification(animate);
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to reset", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return false;
@@ -989,6 +994,7 @@
                             scale, Float.NaN, Float.NaN, animate);
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to set scale", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return false;
@@ -1020,6 +1026,7 @@
                             Float.NaN, centerX, centerY, animate);
                 } catch (RemoteException re) {
                     Log.w(LOG_TAG, "Failed to set center", re);
+                    re.rethrowFromSystemServer();
                 }
             }
             return false;
@@ -1254,10 +1261,7 @@
                    Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
                    re.rethrowFromSystemServer();
                }
-           } else {
-               throw new RuntimeException("AccessibilityServiceConnection is null");
            }
-
            return false;
         }
 
@@ -1301,6 +1305,7 @@
                 return connection.performGlobalAction(action);
             } catch (RemoteException re) {
                 Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
+                re.rethrowFromSystemServer();
             }
         }
         return false;
@@ -1349,6 +1354,7 @@
                 return connection.getServiceInfo();
             } catch (RemoteException re) {
                 Log.w(LOG_TAG, "Error while getting AccessibilityServiceInfo", re);
+                re.rethrowFromSystemServer();
             }
         }
         return null;
@@ -1382,6 +1388,7 @@
                 AccessibilityInteractionClient.getInstance().clearCache();
             } catch (RemoteException re) {
                 Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
+                re.rethrowFromSystemServer();
             }
         }
     }
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 75680e6..4019a56 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -688,7 +688,7 @@
 
     /** {@hide} */
     public boolean isEncryptionAware() {
-        return mResolveInfo.serviceInfo.encryptionAware;
+        return mResolveInfo.serviceInfo.directBootAware;
     }
 
     /**
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index 14aabcf..7a0c89b 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -43,135 +43,32 @@
  */
 public final class GestureDescription {
     /** Gestures may contain no more than this many strokes */
-    public static final int MAX_STROKE_COUNT = 10;
+    private static final int MAX_STROKE_COUNT = 10;
 
     /**
      * Upper bound on total gesture duration. Nearly all gestures will be much shorter.
      */
-    public static final long MAX_GESTURE_DURATION_MS = 60 * 1000;
+    private static final long MAX_GESTURE_DURATION_MS = 60 * 1000;
 
     private final List<StrokeDescription> mStrokes = new ArrayList<>();
     private final float[] mTempPos = new float[2];
 
     /**
-     * Create a description of a click gesture
+     * Get the upper limit for the number of strokes a gesture may contain.
      *
-     * @param x The x coordinate to click. Must not be negative.
-     * @param y The y coordinate to click. Must not be negative.
-     *
-     * @return A description of a click at (x, y)
+     * @return The maximum number of strokes.
      */
-    public static GestureDescription createClick(@IntRange(from = 0) int x,
-            @IntRange(from = 0) int y) {
-        Path clickPath = new Path();
-        clickPath.moveTo(x, y);
-        clickPath.lineTo(x + 1, y);
-        return new GestureDescription(
-                new StrokeDescription(clickPath, 0, ViewConfiguration.getTapTimeout()));
+    public static int getMaxStrokeCount() {
+        return MAX_STROKE_COUNT;
     }
 
     /**
-     * Create a description of a long click gesture
+     * Get the upper limit on a gesture's duration.
      *
-     * @param x The x coordinate to click. Must not be negative.
-     * @param y The y coordinate to click. Must not be negative.
-     *
-     * @return A description of a click at (x, y)
+     * @return The maximum duration in milliseconds.
      */
-    public static GestureDescription createLongClick(@IntRange(from = 0) int x,
-            @IntRange(from = 0) int y) {
-        Path clickPath = new Path();
-        clickPath.moveTo(x, y);
-        clickPath.lineTo(x + 1, y);
-        int longPressTime = ViewConfiguration.getLongPressTimeout();
-        return new GestureDescription(
-                new StrokeDescription(clickPath, 0, longPressTime + (longPressTime / 2)));
-    }
-
-    /**
-     * Create a description of a swipe gesture
-     *
-     * @param startX The x coordinate of the starting point. Must not be negative.
-     * @param startY The y coordinate of the starting point. Must not be negative.
-     * @param endX The x coordinate of the ending point. Must not be negative.
-     * @param endY The y coordinate of the ending point. Must not be negative.
-     * @param duration The time, in milliseconds, to complete the gesture. Must not be negative.
-     *
-     * @return A description of a swipe from ({@code startX}, {@code startY}) to
-     * ({@code endX}, {@code endY}) that takes {@code duration} milliseconds. Returns {@code null}
-     * if the path specified for the swipe is invalid.
-     */
-    public static GestureDescription createSwipe(@IntRange(from = 0) int startX,
-            @IntRange(from = 0) int startY,
-            @IntRange(from = 0) int endX,
-            @IntRange(from = 0) int endY,
-            @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long duration) {
-        Path swipePath = new Path();
-        swipePath.moveTo(startX, startY);
-        swipePath.lineTo(endX, endY);
-        return new GestureDescription(new StrokeDescription(swipePath, 0, duration));
-    }
-
-    /**
-     * Create a description for a pinch (or zoom) gesture.
-     *
-     * @param centerX The x coordinate of the center of the pinch. Must not be negative.
-     * @param centerY The y coordinate of the center of the pinch. Must not be negative.
-     * @param startSpacing The spacing of the touch points at the beginning of the gesture. Must not
-     * be negative.
-     * @param endSpacing The spacing of the touch points at the end of the gesture. Must not be
-     * negative.
-     * @param orientation The angle, in degrees, of the gesture. 0 represents a horizontal pinch
-     * @param duration The time, in milliseconds, to complete the gesture. Must not be negative.
-     *
-     * @return A description of a pinch centered at ({code centerX}, {@code centerY}) that starts
-     * with the touch points spaced by {@code startSpacing} and ends with them spaced by
-     * {@code endSpacing} that lasts {@code duration} ms. Returns {@code null} if either path
-     * specified for the pinch is invalid.
-     */
-    public static GestureDescription createPinch(@IntRange(from = 0) int centerX,
-            @IntRange(from = 0) int centerY,
-            @IntRange(from = 0) int startSpacing,
-            @IntRange(from = 0) int endSpacing,
-            float orientation,
-            @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long duration) {
-        if ((startSpacing < 0) || (endSpacing < 0)) {
-            throw new IllegalArgumentException("Pinch spacing cannot be negative");
-        }
-        float[] startPoint1 = new float[2];
-        float[] endPoint1 = new float[2];
-        float[] startPoint2 = new float[2];
-        float[] endPoint2 = new float[2];
-
-        /* Build points for a horizontal gesture centered at the origin */
-        startPoint1[0] = startSpacing / 2;
-        startPoint1[1] = 0;
-        endPoint1[0] = endSpacing / 2;
-        endPoint1[1] = 0;
-        startPoint2[0] = -startSpacing / 2;
-        startPoint2[1] = 0;
-        endPoint2[0] = -endSpacing / 2;
-        endPoint2[1] = 0;
-
-        /* Rotate and translate the points */
-        Matrix matrix = new Matrix();
-        matrix.setRotate(orientation);
-        matrix.postTranslate(centerX, centerY);
-        matrix.mapPoints(startPoint1);
-        matrix.mapPoints(endPoint1);
-        matrix.mapPoints(startPoint2);
-        matrix.mapPoints(endPoint2);
-
-        Path path1 = new Path();
-        path1.moveTo(startPoint1[0], startPoint1[1]);
-        path1.lineTo(endPoint1[0], endPoint1[1]);
-        Path path2 = new Path();
-        path2.moveTo(startPoint2[0], startPoint2[1]);
-        path2.lineTo(endPoint2[0], endPoint2[1]);
-
-        return new GestureDescription(Arrays.asList(
-                new StrokeDescription(path1, 0, duration),
-                new StrokeDescription(path2, 0, duration)));
+    public static long getMaxGestureDuration() {
+        return MAX_GESTURE_DURATION_MS;
     }
 
     private GestureDescription() {}
@@ -180,10 +77,6 @@
         mStrokes.addAll(strokes);
     }
 
-    private GestureDescription(StrokeDescription stroke) {
-        mStrokes.add(stroke);
-    }
-
     /**
      * Get the number of stroke in the gesture.
      *
@@ -278,21 +171,23 @@
          */
         public Builder addStroke(@NonNull StrokeDescription strokeDescription) {
             if (mStrokes.size() >= MAX_STROKE_COUNT) {
-                throw new RuntimeException("Attempting to add too many strokes to a gesture");
+                throw new IllegalStateException(
+                        "Attempting to add too many strokes to a gesture");
             }
 
             mStrokes.add(strokeDescription);
 
             if (getTotalDuration(mStrokes) > MAX_GESTURE_DURATION_MS) {
                 mStrokes.remove(strokeDescription);
-                throw new RuntimeException("Gesture would exceed maximum duration with new stroke");
+                throw new IllegalStateException(
+                        "Gesture would exceed maximum duration with new stroke");
             }
             return this;
         }
 
         public GestureDescription build() {
             if (mStrokes.size() == 0) {
-                throw new RuntimeException("Gestures must have at least one stroke");
+                throw new IllegalStateException("Gestures must have at least one stroke");
             }
             return new GestureDescription(mStrokes);
         }
@@ -317,8 +212,8 @@
          * Must not be negative.
          */
         public StrokeDescription(@NonNull Path path,
-                @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long startTime,
-                @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long duration) {
+                @IntRange(from = 0) long startTime,
+                @IntRange(from = 0) long duration) {
             if (duration <= 0) {
                 throw new IllegalArgumentException("Duration must be positive");
             }
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 0b751b2..efb9192 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -373,6 +373,7 @@
      * @param values A set of values that the animation will animate between over time.
      * @return An ObjectAnimator object that is set up to animate between the given values.
      */
+    @SafeVarargs
     public static <T> ObjectAnimator ofMultiInt(Object target, String propertyName,
             TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values) {
         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiInt(propertyName, converter,
@@ -569,6 +570,7 @@
      * @param values A set of values that the animation will animate between over time.
      * @return An ObjectAnimator object that is set up to animate between the given values.
      */
+    @SafeVarargs
     public static <T> ObjectAnimator ofMultiFloat(Object target, String propertyName,
             TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values) {
         PropertyValuesHolder pvh = PropertyValuesHolder.ofMultiFloat(propertyName, converter,
@@ -642,6 +644,7 @@
      * @return An ObjectAnimator object that is set up to animate between the given values.
      */
     @NonNull
+    @SafeVarargs
     public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property,
             TypeEvaluator<V> evaluator, V... values) {
         ObjectAnimator anim = new ObjectAnimator(target, property);
@@ -670,6 +673,7 @@
      * @return An ObjectAnimator object that is set up to animate between the given values.
      */
     @NonNull
+    @SafeVarargs
     public static <T, V, P> ObjectAnimator ofObject(T target, Property<T, P> property,
             TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values) {
         PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, evaluator,
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 6ba5b96..ffea6f5 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -236,6 +236,7 @@
      * @see ObjectAnimator#ofMultiInt(Object, String, TypeConverter, TypeEvaluator, Object[])
      * @see ObjectAnimator#ofPropertyValuesHolder(Object, PropertyValuesHolder...)
      */
+    @SafeVarargs
     public static <V> PropertyValuesHolder ofMultiInt(String propertyName,
             TypeConverter<V, int[]> converter, TypeEvaluator<V> evaluator, V... values) {
         return new MultiIntValuesHolder(propertyName, converter, evaluator, values);
@@ -353,6 +354,7 @@
      * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
      * @see ObjectAnimator#ofMultiFloat(Object, String, TypeConverter, TypeEvaluator, Object[])
      */
+    @SafeVarargs
     public static <V> PropertyValuesHolder ofMultiFloat(String propertyName,
             TypeConverter<V, float[]> converter, TypeEvaluator<V> evaluator, V... values) {
         return new MultiFloatValuesHolder(propertyName, converter, evaluator, values);
@@ -438,6 +440,7 @@
      * @param values The values that the property will animate between.
      * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
      */
+    @SafeVarargs
     public static <V> PropertyValuesHolder ofObject(Property property,
             TypeEvaluator<V> evaluator, V... values) {
         PropertyValuesHolder pvh = new PropertyValuesHolder(property);
@@ -465,6 +468,7 @@
      * @see #setConverter(TypeConverter)
      * @see TypeConverter
      */
+    @SafeVarargs
     public static <T, V> PropertyValuesHolder ofObject(Property<?, V> property,
             TypeConverter<T, V> converter, TypeEvaluator<T> evaluator, T... values) {
         PropertyValuesHolder pvh = new PropertyValuesHolder(property);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a0a599e..cc1d68e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -744,7 +744,7 @@
     Activity mParent;
     boolean mCalled;
     /*package*/ boolean mResumed;
-    private boolean mStopped;
+    /*package*/ boolean mStopped;
     boolean mFinished;
     boolean mStartedActivity;
     private boolean mDestroyed;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index f178455..167e6cb 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -621,6 +621,7 @@
      * @see android.transition.Transition#setEpicenterCallback(
      *          android.transition.Transition.EpicenterCallback)
      */
+    @SafeVarargs
     public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
             Pair<View, String>... sharedElements) {
         ActivityOptions opts = new ActivityOptions();
@@ -710,6 +711,10 @@
 
     /** @hide */
     public ActivityOptions(Bundle opts) {
+        // If the remote side sent us bad parcelables, they won't get the
+        // results they want, which is their loss.
+        opts.setDefusable(true);
+
         mPackageName = opts.getString(KEY_PACKAGE_NAME);
         try {
             mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 060ac5e..dbc6c84 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -379,6 +379,33 @@
                         ? "no component name" : componentName.toShortString())
                 + "}";
         }
+
+        public String getStateString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("ActivityClientRecord{");
+            sb.append("paused=").append(paused);
+            sb.append(", stopped=").append(stopped);
+            sb.append(", hideForNow=").append(hideForNow);
+            sb.append(", startsNotResumed=").append(startsNotResumed);
+            sb.append(", isForward=").append(isForward);
+            sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
+            sb.append(", onlyLocalRequest=").append(onlyLocalRequest);
+            sb.append(", preserveWindow=").append(mPreserveWindow);
+            if (activity != null) {
+                sb.append(", Activity{");
+                sb.append("resumed=").append(activity.mResumed);
+                sb.append(", stopped=").append(activity.mStopped);
+                sb.append(", finished=").append(activity.isFinishing());
+                sb.append(", destroyed=").append(activity.isDestroyed());
+                sb.append(", startedActivity=").append(activity.mStartedActivity);
+                sb.append(", temporaryPause=").append(activity.mTemporaryPause);
+                sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
+                sb.append(", visibleBehind=").append(activity.mVisibleBehind);
+                sb.append("}");
+            }
+            sb.append("}");
+            return sb.toString();
+        }
     }
 
     final class ProviderClientRecord {
@@ -3752,9 +3779,10 @@
                     return;
                 }
                 RuntimeException e = new RuntimeException(
-                        "Performing stop of activity that is not resumed: "
+                        "Performing stop of activity that is already stopped: "
                         + r.intent.getComponent().toShortString());
                 Slog.e(TAG, e.getMessage(), e);
+                Slog.e(TAG, r.getStateString());
             }
 
             if (info != null) {
@@ -5208,9 +5236,9 @@
 
             // Setup a location to store generated/compiled graphics code and
             // JIT profiling data. Note that this data is stored in a
-            // device-encrypted storage area, so these caches must never contain
+            // device-protected storage area, so these caches must never contain
             // user sensitive user data.
-            final Context deviceContext = appContext.createDeviceEncryptedStorageContext();
+            final Context deviceContext = appContext.createDeviceProtectedStorageContext();
             final File codeCacheDir = deviceContext.getCodeCacheDir();
             if (codeCacheDir != null) {
                 setupGraphicsSupport(data.info, codeCacheDir);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index cefb22d..5ef03d1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2025,6 +2025,15 @@
     }
 
     @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        try {
+            mPM.flushPackageRestrictionsAsUser(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle user) {
         try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 32ace14..63a6829 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -400,7 +400,7 @@
      *
      * @return the number of files moved, or -1 if there was trouble.
      */
-    private static int migrateFiles(File sourceDir, File targetDir, final String prefix) {
+    private static int moveFiles(File sourceDir, File targetDir, final String prefix) {
         final File[] sourceFiles = FileUtils.listFilesOrEmpty(sourceDir, new FilenameFilter() {
             @Override
             public boolean accept(File dir, String name) {
@@ -430,12 +430,12 @@
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
         synchronized (ContextImpl.class) {
             final File source = sourceContext.getSharedPreferencesPath(name);
             final File target = getSharedPreferencesPath(name);
 
-            final int res = migrateFiles(source.getParentFile(), target.getParentFile(),
+            final int res = moveFiles(source.getParentFile(), target.getParentFile(),
                     source.getName());
             if (res > 0) {
                 // We moved at least one file, so evict any in-memory caches for
@@ -681,11 +681,11 @@
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
         synchronized (ContextImpl.class) {
             final File source = sourceContext.getDatabasePath(name);
             final File target = getDatabasePath(name);
-            return migrateFiles(source.getParentFile(), target.getParentFile(),
+            return moveFiles(source.getParentFile(), target.getParentFile(),
                     source.getName()) != -1;
         }
     }
@@ -1332,9 +1332,14 @@
             }
         }
         try {
-            return ActivityManagerNative.getDefault().registerReceiver(
+            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
                     mMainThread.getApplicationThread(), mBasePackageName,
                     rd, filter, broadcastPermission, userId);
+            if (intent != null) {
+                intent.setExtrasClassLoader(getClassLoader());
+                intent.prepareToEnterProcess();
+            }
+            return intent;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1900,17 +1905,17 @@
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
-        final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE)
-                | Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE;
+    public Context createDeviceProtectedStorageContext() {
+        final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
+                | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
                 mUser, flags, mDisplay, null, Display.INVALID_DISPLAY);
     }
 
     @Override
-    public Context createCredentialEncryptedStorageContext() {
-        final int flags = (mFlags & ~Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE)
-                | Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE;
+    public Context createCredentialProtectedStorageContext() {
+        final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
+                | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
                 mUser, flags, mDisplay, null, Display.INVALID_DISPLAY);
     }
@@ -1921,13 +1926,13 @@
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
-        return (mFlags & Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE) != 0;
+    public boolean isDeviceProtectedStorage() {
+        return (mFlags & Context.CONTEXT_DEVICE_PROTECTED_STORAGE) != 0;
     }
 
     @Override
-    public boolean isCredentialEncryptedStorage() {
-        return (mFlags & Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE) != 0;
+    public boolean isCredentialProtectedStorage() {
+        return (mFlags & Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) != 0;
     }
 
     @Override
@@ -1939,10 +1944,10 @@
     public File getDataDir() {
         if (mPackageInfo != null) {
             File res = null;
-            if (isCredentialEncryptedStorage()) {
-                res = mPackageInfo.getCredentialEncryptedDataDirFile();
-            } else if (isDeviceEncryptedStorage()) {
-                res = mPackageInfo.getDeviceEncryptedDataDirFile();
+            if (isCredentialProtectedStorage()) {
+                res = mPackageInfo.getCredentialProtectedDataDirFile();
+            } else if (isDeviceProtectedStorage()) {
+                res = mPackageInfo.getDeviceProtectedDataDirFile();
             } else {
                 res = mPackageInfo.getDataDirFile();
             }
@@ -2008,13 +2013,13 @@
 
         // If creator didn't specify which storage to use, use the default
         // location for application.
-        if ((flags & (Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE
-                | Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE)) == 0) {
+        if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
+                | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
             final File dataDir = packageInfo.getDataDirFile();
-            if (Objects.equals(dataDir, packageInfo.getCredentialEncryptedDataDirFile())) {
-                flags |= Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE;
-            } else if (Objects.equals(dataDir, packageInfo.getDeviceEncryptedDataDirFile())) {
-                flags |= Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE;
+            if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) {
+                flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
+            } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) {
+                flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
             }
         }
 
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 33fd1db..13e8e75 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.IntDef;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
@@ -49,6 +50,8 @@
 import com.android.internal.content.ReferrerIntent;
 
 import java.io.File;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -78,7 +81,15 @@
     public static final String REPORT_KEY_STREAMRESULT = "stream";
 
     private static final String TAG = "Instrumentation";
-    
+
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
+    public @interface UiAutomationFlags {};
+
+
     private final Object mSync = new Object();
     private ActivityThread mThread = null;
     private MessageQueue mMessageQueue = null;
@@ -1876,7 +1887,7 @@
      *
      * @see UiAutomation
      */
-    public UiAutomation getUiAutomation(int flags) {
+    public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
         if (mUiAutomationConnection != null) {
             if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
                 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index a03fd72..e090aa4 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -16,8 +16,6 @@
 
 package android.app;
 
-import android.text.TextUtils;
-import android.util.ArrayMap;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -37,15 +35,17 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.DisplayAdjustments;
 import android.view.Display;
-import android.os.SystemProperties;
+import android.view.DisplayAdjustments;
 
 import dalvik.system.VMRuntime;
 
@@ -56,11 +56,10 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.URL;
-import java.util.List;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Objects;
 
 final class IntentReceiverLeaked extends AndroidRuntimeException {
@@ -95,8 +94,8 @@
     private String mDataDir;
     private String mLibDir;
     private File mDataDirFile;
-    private File mDeviceEncryptedDataDirFile;
-    private File mCredentialEncryptedDataDirFile;
+    private File mDeviceProtectedDataDirFile;
+    private File mCredentialProtectedDataDirFile;
     private final ClassLoader mBaseClassLoader;
     private final boolean mSecurityViolation;
     private final boolean mIncludeCode;
@@ -186,8 +185,8 @@
         mSharedLibraries = null;
         mDataDir = null;
         mDataDirFile = null;
-        mDeviceEncryptedDataDirFile = null;
-        mCredentialEncryptedDataDirFile = null;
+        mDeviceProtectedDataDirFile = null;
+        mCredentialProtectedDataDirFile = null;
         mLibDir = null;
         mBaseClassLoader = null;
         mSecurityViolation = false;
@@ -303,8 +302,8 @@
         mDataDir = aInfo.dataDir;
         mLibDir = aInfo.nativeLibraryDir;
         mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
-        mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
-        mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
+        mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
+        mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
     }
 
     public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
@@ -651,12 +650,12 @@
         return mDataDirFile;
     }
 
-    public File getDeviceEncryptedDataDirFile() {
-        return mDeviceEncryptedDataDirFile;
+    public File getDeviceProtectedDataDirFile() {
+        return mDeviceProtectedDataDirFile;
     }
 
-    public File getCredentialEncryptedDataDirFile() {
-        return mCredentialEncryptedDataDirFile;
+    public File getCredentialProtectedDataDirFile() {
+        return mCredentialProtectedDataDirFile;
     }
 
     public AssetManager getAssets(ActivityThread mainThread) {
@@ -913,6 +912,8 @@
                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                 mStrongRef = strong ? rd : null;
             }
+
+            @Override
             public void performReceive(Intent intent, int resultCode, String data,
                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
@@ -996,6 +997,7 @@
                 try {
                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
                     intent.setExtrasClassLoader(cl);
+                    intent.prepareToEnterProcess();
                     setExtrasClassLoader(cl);
                     receiver.setPendingResult(this);
                     receiver.onReceive(mContext, intent);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 132b6dd..cb1bee5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -957,7 +957,7 @@
             if (in.readInt() == 1) {
                 actionIntent = PendingIntent.CREATOR.createFromParcel(in);
             }
-            mExtras = in.readBundle();
+            mExtras = Bundle.setDefusable(in.readBundle(), true);
             mRemoteInputs = in.createTypedArray(RemoteInput.CREATOR);
         }
 
@@ -1487,7 +1487,7 @@
 
         mSortKey = parcel.readString();
 
-        extras = parcel.readBundle(); // may be null
+        extras = Bundle.setDefusable(parcel.readBundle(), true); // may be null
 
         actions = parcel.createTypedArray(Action.CREATOR); // may be null
 
@@ -3197,6 +3197,7 @@
         }
 
         private void resetStandardTemplateWithActions(RemoteViews big) {
+            big.setViewVisibility(R.id.actions_container, View.GONE);
             big.setViewVisibility(R.id.actions, View.GONE);
             big.removeAllViews(R.id.actions);
 
@@ -3218,6 +3219,7 @@
 
             int N = mActions.size();
             if (N > 0) {
+                big.setViewVisibility(R.id.actions_container, View.VISIBLE);
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 for (int i=0; i<N; i++) {
@@ -4580,13 +4582,13 @@
 
         private void buildIntoRemoteViewContent(RemoteViews remoteViews,
                 RemoteViews customContent) {
-            remoteViews.removeAllViews(R.id.notification_main_column);
-            // Need to clone customContent before adding, because otherwise it can no longer be
-            // parceled independently of remoteViews.
             if (customContent != null) {
+                // Need to clone customContent before adding, because otherwise it can no longer be
+                // parceled independently of remoteViews.
                 customContent = customContent.clone();
+                remoteViews.removeAllViews(R.id.notification_main_column);
+                remoteViews.addView(R.id.notification_main_column, customContent);
             }
-            remoteViews.addView(R.id.notification_main_column, customContent);
             // also update the end margin if there is an image
             int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
                     R.dimen.notification_content_margin_end);
@@ -4689,13 +4691,13 @@
 
         private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id,
                 RemoteViews customContent) {
-            remoteViews.removeAllViews(id);
-            // Need to clone customContent before adding, because otherwise it can no longer be
-            // parceled independently of remoteViews.
             if (customContent != null) {
+                // Need to clone customContent before adding, because otherwise it can no longer be
+                // parceled independently of remoteViews.
                 customContent = customContent.clone();
+                remoteViews.removeAllViews(id);
+                remoteViews.addView(id, customContent);
             }
-            remoteViews.addView(id, customContent);
             return remoteViews;
         }
     }
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 3be2cdc..dd70b5d 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -268,7 +268,7 @@
             "android.app.action.BUGREPORT_SHARE";
 
     /**
-     * Broadcast action: notify that a new batch of device logs is ready to be collected.
+     * Broadcast action: notify that a new batch of security logs is ready to be collected.
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -623,13 +623,13 @@
     }
 
     /**
-     * Called when a new batch of device logs can be retrieved.
+     * Called when a new batch of security logs can be retrieved.
      *
      * <p>This callback is only applicable to device owners.
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
-     * @see DevicePolicyManager#retrieveDeviceLogs(ComponentName)
+     * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName)
      */
     public void onSecurityLogsAvailable(Context context, Intent intent) {
     }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9094912..b7d9b80 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -25,7 +25,7 @@
 import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
-import android.auditing.SecurityLog.SecurityEvent;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -5787,63 +5787,80 @@
     }
 
     /**
-     * Called by device owner to control the device logging feature. Logging can only be enabled on
-     * single user devices where the sole user is managed by the device owner.
-     * <p>
-     * Device logs contain various information intended for security auditing purposes. See
-     * {@link SecurityEvent} for details.
-     * <p>
-     * There must be only one user on the device, managed by the device owner. Otherwise a
-     * {@link SecurityException} will be thrown.
+     * Called by device owner to control the security logging feature. Logging can only be
+     * enabled on single user devices where the sole user is managed by the device owner.
+     *
+     * <p> Security logs contain various information intended for security auditing purposes.
+     * See {@link SecurityEvent} for details.
+     *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @param enabled whether device logging should be enabled or not.
+     * @param enabled whether security logging should be enabled or not.
      * @throws SecurityException if {@code admin} is not a device owner.
-     * @see #retrieveDeviceLogs
+     * @see #retrieveSecurityLogs
+     */
+    public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+        try {
+            mService.setSecurityLoggingEnabled(admin, enabled);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
      */
     public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+        setSecurityLoggingEnabled(admin, enabled);
+    }
+
+    /**
+     * Return whether security logging is enabled or not by the device owner.
+     *
+     * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
+     * thrown.
+     *
+     * @param admin Which device owner this request is associated with.
+     * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
         try {
-            mService.setDeviceLoggingEnabled(admin, enabled);
+            return mService.isSecurityLoggingEnabled(admin);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Return whether device logging is enabled or not by the device owner.
-     * <p>
-     * Can only be called by the device owner, otherwise a {@link SecurityException} will be thrown.
-     *
-     * @param admin Which device owner this request is associated with.
-     * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not a device owner.
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
      */
     public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
-        try {
-            return mService.getDeviceLoggingEnabled(admin);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
+        return isSecurityLoggingEnabled(admin);
     }
 
     /**
-     * Called by device owner to retrieve all new device logging entries since the last call to this
-     * API after device boots.
-     * <p>
-     * Access to the logs is rate limited and it will only return new logs after the device owner
-     * has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
-     * <p>
-     * There must be only one user on the device, managed by the device owner. Otherwise a
-     * {@link SecurityException} will be thrown.
+     * Called by device owner to retrieve all new security logging entries since the last call to
+     * this API after device boots.
+     *
+     * <p> Access to the logs is rate limited and it will only return new logs after the device
+     * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
+     *
+     * <p>There must be only one user on the device, managed by the device owner.
+     * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @return the new batch of device logs which is a list of {@link SecurityEvent}, or
-     *         {@code null} if rate limitation is exceeded or if logging is currently disabled.
+     * @return the new batch of security logs which is a list of {@link SecurityEvent},
+     * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+    public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrieveDeviceLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
             if (list != null) {
                 return list.getList();
             } else {
@@ -5856,6 +5873,14 @@
     }
 
     /**
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+        return retrieveSecurityLogs(admin);
+    }
+
+    /**
      * Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent
      * profile.
      *
@@ -5886,9 +5911,9 @@
      * @return Device logs from before the latest reboot of the system.
      * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
+    public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) {
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
             return list.getList();
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
@@ -5896,6 +5921,14 @@
     }
 
     /**
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
+        return retrievePreRebootSecurityLogs(admin);
+    }
+
+    /**
      * Called by a profile owner of a managed profile to set the color used for customization. This
      * color is used as background color of the confirm credentials screen for that user. The
      * default color is {@link android.graphics.Color#GRAY}.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c38496d..3ba5bd8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -290,10 +290,10 @@
     void setAffiliationIds(in ComponentName admin, in List<String> ids);
     boolean isAffiliatedUser();
 
-    void setDeviceLoggingEnabled(in ComponentName admin, boolean enabled);
-    boolean getDeviceLoggingEnabled(in ComponentName admin);
-    ParceledListSlice retrieveDeviceLogs(in ComponentName admin);
-    ParceledListSlice retrievePreviousDeviceLogs(in ComponentName admin);
+    void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
+    boolean isSecurityLoggingEnabled(in ComponentName admin);
+    ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
+    ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
 
     boolean isUninstallInQueue(String packageName);
     void uninstallPackageWithActiveAdmins(String packageName);
diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
similarity index 98%
rename from core/java/android/auditing/SecurityLog.java
rename to core/java/android/app/admin/SecurityLog.java
index 13823a2..001a81d 100644
--- a/core/java/android/auditing/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.auditing;
+package android.app.admin;
 
 import android.annotation.IntDef;
 import android.os.Parcel;
@@ -92,7 +92,7 @@
     public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
 
     /**
-     * Returns if device logging is enabled. Log producers should only write new logs if this is
+     * Returns if security logging is enabled. Log producers should only write new logs if this is
      * true. Under the hood this is the logical AND of whether device owner exists and whether
      * it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
      * @hide
diff --git a/core/java/android/auditing/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
similarity index 93%
rename from core/java/android/auditing/SecurityLogTags.logtags
rename to core/java/android/app/admin/SecurityLogTags.logtags
index ccc3799..39371c7 100644
--- a/core/java/android/auditing/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -1,6 +1,6 @@
 # See system/core/logcat/event.logtags for a description of the format of this file.
 
-option java_package android.auditing
+option java_package android.app.admin
 
 210001 security_adb_shell_interactive
 210002 security_adb_shell_command               (command|3)
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index aeb3156..801c951 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -18,7 +18,6 @@
 
 import android.app.IBackupAgent;
 import android.app.QueuedWork;
-import android.app.backup.IBackupManager;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.ApplicationInfo;
@@ -36,18 +35,17 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 /**
  * Provides the central interface between an
  * application and Android's data backup infrastructure.  An application that wishes
@@ -310,7 +308,7 @@
 
         // System apps have control over where their default storage context
         // is pointed, so we're always explicit when building paths.
-        final Context ceContext = createCredentialEncryptedStorageContext();
+        final Context ceContext = createCredentialProtectedStorageContext();
         final String rootDir = ceContext.getDataDir().getCanonicalPath();
         final String filesDir = ceContext.getFilesDir().getCanonicalPath();
         final String noBackupDir = ceContext.getNoBackupFilesDir().getCanonicalPath();
@@ -321,7 +319,7 @@
         final String cacheDir = ceContext.getCacheDir().getCanonicalPath();
         final String codeCacheDir = ceContext.getCodeCacheDir().getCanonicalPath();
 
-        final Context deContext = createDeviceEncryptedStorageContext();
+        final Context deContext = createDeviceProtectedStorageContext();
         final String deviceRootDir = deContext.getDataDir().getCanonicalPath();
         final String deviceFilesDir = deContext.getFilesDir().getCanonicalPath();
         final String deviceNoBackupDir = deContext.getNoBackupFilesDir().getCanonicalPath();
@@ -516,7 +514,7 @@
         try {
             // System apps have control over where their default storage context
             // is pointed, so we're always explicit when building paths.
-            final Context ceContext = createCredentialEncryptedStorageContext();
+            final Context ceContext = createCredentialProtectedStorageContext();
             rootDir = ceContext.getDataDir().getCanonicalPath();
             filesDir = ceContext.getFilesDir().getCanonicalPath();
             nbFilesDir = ceContext.getNoBackupFilesDir().getCanonicalPath();
@@ -525,7 +523,7 @@
             cacheDir = ceContext.getCacheDir().getCanonicalPath();
             codeCacheDir = ceContext.getCodeCacheDir().getCanonicalPath();
 
-            final Context deContext = createDeviceEncryptedStorageContext();
+            final Context deContext = createDeviceProtectedStorageContext();
             deviceRootDir = deContext.getDataDir().getCanonicalPath();
             deviceFilesDir = deContext.getFilesDir().getCanonicalPath();
             deviceNbFilesDir = deContext.getNoBackupFilesDir().getCanonicalPath();
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index cdc80e3..478024d 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.XmlResourceParser;
-import android.os.*;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -31,16 +31,15 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.xmlpull.v1.XmlPullParserException;
 /**
  * Global constant definitions et cetera related to the full-backup-to-fd
  * binary format.  Nothing in this namespace is part of any API; it's all
@@ -289,7 +288,7 @@
 
             // System apps have control over where their default storage context
             // is pointed, so we're always explicit when building paths.
-            final Context ceContext = context.createCredentialEncryptedStorageContext();
+            final Context ceContext = context.createCredentialProtectedStorageContext();
             FILES_DIR = ceContext.getFilesDir();
             DATABASE_DIR = ceContext.getDatabasePath("foo").getParentFile();
             ROOT_DIR = ceContext.getDataDir();
@@ -297,7 +296,7 @@
             CACHE_DIR = ceContext.getCacheDir();
             NOBACKUP_DIR = ceContext.getNoBackupFilesDir();
 
-            final Context deContext = context.createDeviceEncryptedStorageContext();
+            final Context deContext = context.createDeviceProtectedStorageContext();
             DEVICE_FILES_DIR = deContext.getFilesDir();
             DEVICE_DATABASE_DIR = deContext.getDatabasePath("foo").getParentFile();
             DEVICE_ROOT_DIR = deContext.getDataDir();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index bbfec41..828ac38 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -73,9 +73,32 @@
     public static final int BACKOFF_POLICY_EXPONENTIAL = 1;
 
     /* Minimum interval for a periodic job, in milliseconds. */
-    public static final long MIN_PERIOD_MILLIS = 60 * 60 * 1000L;   // 60 minutes
+    private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L;   // 15 minutes
+
     /* Minimum flex for a periodic job, in milliseconds. */
-    public static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes
+    private static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes
+
+    /**
+     * Query the minimum interval allowed for periodic scheduled jobs.  Attempting
+     * to declare a smaller period that this when scheduling a job will result in a
+     * job that is still periodic, but will run with this effective period.
+     *
+     * @return The minimum available interval for scheduling periodic jobs, in milliseconds.
+     */
+    public static final long getMinimumPeriod() {
+        return MIN_PERIOD_MILLIS;
+    }
+
+    /**
+     * Query the minimum flex time allowed for periodic scheduled jobs.  Attempting
+     * to declare a shorter flex time than this when scheduling such a job will
+     * result in this amount as the effective flex time for the job.
+     *
+     * @return The minimum available flex time for scheduling periodic jobs, in milliseconds.
+     */
+    public static final long getMinimumFlex() {
+        return MIN_FLEX_MILLIS;
+    }
 
     /**
      * Default type of backoff.
@@ -227,7 +250,7 @@
      * job does not recur periodically.
      */
     public long getIntervalMillis() {
-        return intervalMillis >= MIN_PERIOD_MILLIS ? intervalMillis : MIN_PERIOD_MILLIS;
+        return intervalMillis >= getMinimumPeriod() ? intervalMillis : getMinimumPeriod();
     }
 
     /**
@@ -236,7 +259,7 @@
     public long getFlexMillis() {
         long interval = getIntervalMillis();
         long percentClamp = 5 * interval / 100;
-        long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, MIN_FLEX_MILLIS));
+        long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, getMinimumFlex()));
         return clampedFlex <= interval ? clampedFlex : interval;
     }
 
@@ -565,9 +588,9 @@
          * Specify that this job should recur with the provided interval and flex. The job can
          * execute at any time in a window of flex length at the end of the period.
          * @param intervalMillis Millisecond interval for which this job will repeat. A minimum
-         *                       value of {@link #MIN_PERIOD_MILLIS} is enforced.
+         *                       value of {@link #getMinimumPeriod()} is enforced.
          * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least
-         *                   {@link #MIN_FLEX_MILLIS} or 5 percent of the period, whichever is
+         *                   {@link #getMinimumFlex()} or 5 percent of the period, whichever is
          *                   higher.
          */
         public Builder setPeriodic(long intervalMillis, long flexMillis) {
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 0ec58ea..58630b0 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -836,6 +836,17 @@
         }
     }
 
+    /** {@hide} */
+    public void prepareToEnterProcess() {
+        final int size = mItems.size();
+        for (int i = 0; i < size; i++) {
+            final Item item = mItems.get(i);
+            if (item.mIntent != null) {
+                item.mIntent.prepareToEnterProcess();
+            }
+        }
+    }
+
     /** @hide */
     public void fixUris(int contentUserHint) {
         final int size = mItems.size();
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 1c3f45c..bc2d788 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -394,6 +394,7 @@
         @Override
         public Bundle call(
                 String callingPkg, String method, @Nullable String arg, @Nullable Bundle extras) {
+            Bundle.setDefusable(extras, true);
             final String original = setCallingPackage(callingPkg);
             try {
                 return ContentProvider.this.call(method, arg, extras);
@@ -412,6 +413,7 @@
         @Override
         public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
                 Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
+            Bundle.setDefusable(opts, true);
             validateIncomingUri(uri);
             uri = getUriWithoutUserId(uri);
             enforceFilePermission(callingPkg, uri, "r", null);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 441f188..cd67b3e 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1412,7 +1412,9 @@
             throw new IllegalArgumentException("Unknown URI " + uri);
         }
         try {
-            return provider.call(mPackageName, method, arg, extras);
+            final Bundle res = provider.call(mPackageName, method, arg, extras);
+            Bundle.setDefusable(res, true);
+            return res;
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
             // Manager will kill this process shortly anyway.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c4dfdcf..15cc17d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -691,24 +691,31 @@
      *
      * @see #getSharedPreferencesPath(String)
      * @see #MODE_PRIVATE
+     * @removed
      */
     public abstract SharedPreferences getSharedPreferences(File file, int mode);
 
     /**
-     * Migrate an existing shared preferences file from the given source storage
+     * Move an existing shared preferences file from the given source storage
      * context to this context. This is typically used to migrate data between
-     * storage locations after an upgrade, such as migrating from credential
-     * encrypted to device encrypted storage.
+     * storage locations after an upgrade, such as moving to device protected
+     * storage.
      *
      * @param sourceContext The source context which contains the existing
-     *            shared preferences to migrate.
+     *            shared preferences to move.
      * @param name The name of the shared preferences file.
-     * @return {@code true} if the migration was successful or if the shared
+     * @return {@code true} if the move was successful or if the shared
      *         preferences didn't exist in the source context, otherwise
      *         {@code false}.
-     * @see #createDeviceEncryptedStorageContext()
+     * @see #createDeviceProtectedStorageContext()
      */
-    public abstract boolean migrateSharedPreferencesFrom(Context sourceContext, String name);
+    public abstract boolean moveSharedPreferencesFrom(Context sourceContext, String name);
+
+    /** @removed */
+    @Deprecated
+    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+        return moveSharedPreferencesFrom(sourceContext, name);
+    }
 
     /**
      * Delete an existing shared preferences file.
@@ -807,17 +814,16 @@
      *            to get a path.
      * @return An absolute path to the given file.
      * @see #getSharedPreferences(String, int)
+     * @removed
      */
     public abstract File getSharedPreferencesPath(String name);
 
     /**
      * Returns the absolute path to the directory on the filesystem where all
-     * private files belonging to this app are stored. This is the top-level
-     * directory under which {@link #getFilesDir()}, {@link #getCacheDir()}, etc
-     * are contained. Apps should <em>not</em> create any files or directories
-     * as direct children of this directory, since it's a reserved namespace
-     * belonging to the platform. Instead, use {@link #getDir(String, int)} or
-     * other storage APIs.
+     * private files belonging to this app are stored. Apps should not use this
+     * path directly; they should instead use {@link #getFilesDir()},
+     * {@link #getCacheDir()}, {@link #getDir(String, int)}, or other storage
+     * APIs on this class.
      * <p>
      * The returned path may change over time if the calling app is moved to an
      * adopted storage device, so only relative paths should be persisted.
@@ -825,7 +831,7 @@
      * No additional permissions are required for the calling app to read or
      * write files under the returned path.
      *
-     * @see #getDir(String, int)
+     * @see ApplicationInfo#dataDir
      */
     public abstract File getDataDir();
 
@@ -1397,19 +1403,25 @@
             @Nullable DatabaseErrorHandler errorHandler);
 
     /**
-     * Migrate an existing database file from the given source storage context
-     * to this context. This is typically used to migrate data between storage
-     * locations after an upgrade, such as migrating from credential encrypted
-     * to device encrypted storage.
+     * Move an existing database file from the given source storage context to
+     * this context. This is typically used to migrate data between storage
+     * locations after an upgrade, such as migrating to device protected
+     * storage.
      *
      * @param sourceContext The source context which contains the existing
-     *            database to migrate.
+     *            database to move.
      * @param name The name of the database file.
-     * @return {@code true} if the migration was successful or if the database
-     *         didn't exist in the source context, otherwise {@code false}.
-     * @see #createDeviceEncryptedStorageContext()
+     * @return {@code true} if the move was successful or if the database didn't
+     *         exist in the source context, otherwise {@code false}.
+     * @see #createDeviceProtectedStorageContext()
      */
-    public abstract boolean migrateDatabaseFrom(Context sourceContext, String name);
+    public abstract boolean moveDatabaseFrom(Context sourceContext, String name);
+
+    /** @removed */
+    @Deprecated
+    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+        return moveDatabaseFrom(sourceContext, name);
+    }
 
     /**
      * Delete an existing private SQLiteDatabase associated with this Context's
@@ -4038,19 +4050,19 @@
 
     /**
      * Flag for use with {@link #createPackageContext}: point all file APIs at
-     * device-encrypted storage.
+     * device-protected storage.
      *
      * @hide
      */
-    public static final int CONTEXT_DEVICE_ENCRYPTED_STORAGE = 0x00000008;
+    public static final int CONTEXT_DEVICE_PROTECTED_STORAGE = 0x00000008;
 
     /**
      * Flag for use with {@link #createPackageContext}: point all file APIs at
-     * credential-encrypted storage.
+     * credential-protected storage.
      *
      * @hide
      */
-    public static final int CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE = 0x00000010;
+    public static final int CONTEXT_CREDENTIAL_PROTECTED_STORAGE = 0x00000010;
 
     /**
      * @hide Used to indicate we should tell the activity manager about the process
@@ -4154,53 +4166,73 @@
 
     /**
      * Return a new Context object for the current Context but whose storage
-     * APIs are backed by device-encrypted storage.
+     * APIs are backed by device-protected storage.
      * <p>
-     * Data stored in device-encrypted storage is typically encrypted with a key
-     * tied to the physical device, and it can be accessed when the device has
-     * booted successfully, both <em>before and after</em> the user has
-     * authenticated with their credentials (such as a lock pattern or PIN).
-     * Because device-encrypted data is available before user authentication,
-     * you should carefully consider what data you store using this Context.
+     * On devices with direct boot, data stored in this location is encrypted
+     * with a key tied to the physical device, and it can be accessed
+     * immediately after the device has booted successfully, both
+     * <em>before and after</em> the user has authenticated with their
+     * credentials (such as a lock pattern or PIN).
+     * <p>
+     * Because device-protected data is available without user authentication,
+     * you should carefully limit the data you store using this Context. For
+     * example, storing sensitive authentication tokens or passwords in the
+     * device-protected area is strongly discouraged.
      * <p>
      * If the underlying device does not have the ability to store
-     * device-encrypted and credential-encrypted data using different keys, then
-     * both storage areas will become available at the same time. They remain
-     * two distinct storage areas, and only the window of availability changes.
+     * device-protected and credential-protected data using different keys, then
+     * both storage areas will become available at the same time. They remain as
+     * two distinct storage locations on disk, and only the window of
+     * availability changes.
      * <p>
      * Each call to this method returns a new instance of a Context object;
      * Context objects are not shared, however common state (ClassLoader, other
      * Resources for the same configuration) may be so the Context itself can be
      * fairly lightweight.
      *
-     * @see #isDeviceEncryptedStorage()
+     * @see #isDeviceProtectedStorage()
      */
-    public abstract Context createDeviceEncryptedStorageContext();
+    public abstract Context createDeviceProtectedStorageContext();
+
+    /** @removed */
+    @Deprecated
+    public Context createDeviceEncryptedStorageContext() {
+        return createDeviceProtectedStorageContext();
+    }
 
     /**
      * Return a new Context object for the current Context but whose storage
-     * APIs are backed by credential-encrypted storage.
+     * APIs are backed by credential-protected storage. This is the default
+     * storage area for apps unless
+     * {@link android.R.attr#defaultToDeviceProtectedStorage} was requested.
      * <p>
-     * Data stored in credential-encrypted storage is typically encrypted with a
-     * key tied to user credentials, and they can be accessed
+     * On devices with direct boot, data stored in this location is encrypted
+     * with a key tied to user credentials, which can be accessed
      * <em>only after</em> the user has entered their credentials (such as a
      * lock pattern or PIN).
      * <p>
      * If the underlying device does not have the ability to store
-     * device-encrypted and credential-encrypted data using different keys, then
-     * both storage areas will become available at the same time. They remain
-     * two distinct storage areas, and only the window of availability changes.
+     * device-protected and credential-protected data using different keys, then
+     * both storage areas will become available at the same time. They remain as
+     * two distinct storage locations on disk, and only the window of
+     * availability changes.
      * <p>
      * Each call to this method returns a new instance of a Context object;
      * Context objects are not shared, however common state (ClassLoader, other
      * Resources for the same configuration) may be so the Context itself can be
      * fairly lightweight.
      *
-     * @see #isCredentialEncryptedStorage()
+     * @see #isCredentialProtectedStorage()
      * @hide
      */
     @SystemApi
-    public abstract Context createCredentialEncryptedStorageContext();
+    public abstract Context createCredentialProtectedStorageContext();
+
+    /** @removed */
+    @Deprecated
+    public Context createCredentialEncryptedStorageContext() {
+        return createCredentialProtectedStorageContext();
+    }
 
     /**
      * Gets the display adjustments holder for this context.  This information
@@ -4226,19 +4258,31 @@
 
     /**
      * Indicates if the storage APIs of this Context are backed by
-     * device-encrypted storage.
+     * device-protected storage.
      *
-     * @see #createDeviceEncryptedStorageContext()
+     * @see #createDeviceProtectedStorageContext()
      */
-    public abstract boolean isDeviceEncryptedStorage();
+    public abstract boolean isDeviceProtectedStorage();
+
+    /** @removed */
+    @Deprecated
+    public boolean isDeviceEncryptedStorage() {
+        return isDeviceProtectedStorage();
+    }
 
     /**
      * Indicates if the storage APIs of this Context are backed by
-     * credential-encrypted storage.
+     * credential-protected storage.
      *
-     * @see #createCredentialEncryptedStorageContext()
+     * @see #createCredentialProtectedStorageContext()
      * @hide
      */
     @SystemApi
-    public abstract boolean isCredentialEncryptedStorage();
+    public abstract boolean isCredentialProtectedStorage();
+
+    /** @removed */
+    @Deprecated
+    public boolean isCredentialEncryptedStorage() {
+        return isCredentialProtectedStorage();
+    }
 }
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 323c9bf..b2df207 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -33,8 +33,8 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.UserHandle;
-import android.view.DisplayAdjustments;
 import android.view.Display;
+import android.view.DisplayAdjustments;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -170,8 +170,8 @@
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
-        return mBase.migrateSharedPreferencesFrom(sourceContext, name);
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
+        return mBase.moveSharedPreferencesFrom(sourceContext, name);
     }
 
     @Override
@@ -288,8 +288,8 @@
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
-        return mBase.migrateDatabaseFrom(sourceContext, name);
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
+        return mBase.moveDatabaseFrom(sourceContext, name);
     }
 
     @Override
@@ -818,26 +818,26 @@
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
-        return mBase.createDeviceEncryptedStorageContext();
+    public Context createDeviceProtectedStorageContext() {
+        return mBase.createDeviceProtectedStorageContext();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public Context createCredentialEncryptedStorageContext() {
-        return mBase.createCredentialEncryptedStorageContext();
+    public Context createCredentialProtectedStorageContext() {
+        return mBase.createCredentialProtectedStorageContext();
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
-        return mBase.isDeviceEncryptedStorage();
+    public boolean isDeviceProtectedStorage() {
+        return mBase.isDeviceProtectedStorage();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public boolean isCredentialEncryptedStorage() {
-        return mBase.isCredentialEncryptedStorage();
+    public boolean isCredentialProtectedStorage() {
+        return mBase.isCredentialProtectedStorage();
     }
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 35dbc34..57ab7a2 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -23,12 +23,14 @@
 import android.annotation.SystemApi;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -1946,31 +1948,48 @@
     public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
 
     /**
-     * Broadcast Action: This is broadcast once, after the system has finished
-     * booting and the user is in a "locked" state. A user is locked when their
-     * credential-encrypted private app data storage is unavailable. Once the
-     * user has entered their credentials (such as a lock pattern or PIN) for
-     * the first time, the {@link #ACTION_BOOT_COMPLETED} broadcast will be
-     * sent.
+     * Broadcast Action: This is broadcast once, after the user has finished
+     * booting, but while still in the "locked" state. It can be used to perform
+     * application-specific initialization, such as installing alarms. You must
+     * hold the {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED}
+     * permission in order to receive this broadcast.
      * <p>
-     * You must hold the
-     * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in
-     * order to receive this broadcast.
+     * This broadcast is sent immediately at boot by all devices (regardless of
+     * direct boot support) running {@link android.os.Build.VERSION_CODES#N} or
+     * higher. Upon receipt of this broadcast, the user is still locked and only
+     * device-protected storage can be accessed safely. If you want to access
+     * credential-protected storage, you need to wait for the user to be
+     * unlocked (typically by entering their lock pattern or PIN for the first
+     * time), after which the {@link #ACTION_USER_UNLOCKED} and
+     * {@link #ACTION_BOOT_COMPLETED} broadcasts are sent.
+     * <p>
+     * To receive this broadcast, your receiver component must be marked as
+     * being {@link ComponentInfo#directBootAware}.
      * <p class="note">
      * This is a protected intent that can only be sent by the system.
+     *
+     * @see Context#createDeviceProtectedStorageContext()
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
 
     /**
-     * Broadcast Action: This is broadcast once, after the system has finished
-     * booting.  It can be used to perform application-specific initialization,
-     * such as installing alarms.  You must hold the
-     * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission
-     * in order to receive this broadcast.
-     *
-     * <p class="note">This is a protected intent that can only be sent
-     * by the system.
+     * Broadcast Action: This is broadcast once, after the user has finished
+     * booting. It can be used to perform application-specific initialization,
+     * such as installing alarms. You must hold the
+     * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in
+     * order to receive this broadcast.
+     * <p>
+     * This broadcast is sent at boot by all devices (both with and without
+     * direct boot support). Upon receipt of this broadcast, the user is
+     * unlocked and both device-protected and credential-protected storage can
+     * accessed safely.
+     * <p>
+     * If you need to run while the user is still locked (before they've entered
+     * their lock pattern or PIN for the first time), you can listen for the
+     * {@link #ACTION_LOCKED_BOOT_COMPLETED} broadcast.
+     * <p class="note">
+     * This is a protected intent that can only be sent by the system.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
@@ -6037,13 +6056,20 @@
         return mExtras != null && mExtras.hasFileDescriptors();
     }
 
-    /** @hide */
+    /** {@hide} */
     public void setAllowFds(boolean allowFds) {
         if (mExtras != null) {
             mExtras.setAllowFds(allowFds);
         }
     }
 
+    /** {@hide} */
+    public void setDefusable(boolean defusable) {
+        if (mExtras != null) {
+            mExtras.setDefusable(defusable);
+        }
+    }
+
     /**
      * Retrieve extended data from the intent.
      *
@@ -8938,6 +8964,17 @@
      * @hide
      */
     public void prepareToEnterProcess() {
+        // We just entered destination process, so we should be able to read all
+        // parcelables inside.
+        setDefusable(true);
+
+        if (mSelector != null) {
+            mSelector.prepareToEnterProcess();
+        }
+        if (mClipData != null) {
+            mClipData.prepareToEnterProcess();
+        }
+
         if (mContentUserHint != UserHandle.USER_CURRENT) {
             if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
                 fixUris(mContentUserHint);
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index f793d76..541ebbd 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -147,7 +147,7 @@
     }
 
     private SyncRequest(Parcel in) {
-        mExtras = in.readBundle();
+        mExtras = Bundle.setDefusable(in.readBundle(), true);
         mSyncFlexTimeSecs = in.readLong();
         mSyncRunTimeSecs = in.readLong();
         mIsPeriodic = (in.readInt() != 0);
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 58d75f7..104feb5 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -16,7 +16,9 @@
 
 package android.content.pm;
 
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -24,7 +26,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
-import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Printer;
 
@@ -109,8 +110,8 @@
      * include/exclude criteria.
      * <p>If android:allowBackup is set to false, this attribute is ignored.
      *
-     * @see {@link android.content.Context#getNoBackupFilesDir}
-     * @see {@link #FLAG_ALLOW_BACKUP}
+     * @see android.content.Context#getNoBackupFilesDir()
+     * @see #FLAG_ALLOW_BACKUP
      *
      * @hide
      */
@@ -469,20 +470,20 @@
     public static final int PRIVATE_FLAG_HAS_DOMAIN_URLS = 1<<4;
 
     /**
-     * When set, default data storage directory for given app is pointed at
-     * device-encrypted location.
+     * When set, the default data storage directory for this app is pointed at
+     * the device-protected location.
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED = 1 << 5;
+    public static final int PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = 1 << 5;
 
     /**
-     * When set, assume that all components under the given app are encryption
+     * When set, assume that all components under the given app are direct boot
      * aware, unless otherwise specified.
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_ENCRYPTION_AWARE = 1 << 6;
+    public static final int PRIVATE_FLAG_DIRECT_BOOT_AWARE = 1 << 6;
 
     /**
      * Value for {@link #privateFlags}: set to {@code true} if the application
@@ -493,11 +494,12 @@
     public static final int PRIVATE_FLAG_AUTOPLAY = 1 << 7;
 
     /**
-     * When set, at least one component inside this application is encryption aware.
+     * When set, at least one component inside this application is direct boot
+     * aware.
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE = 1 << 8;
+    public static final int PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE = 1 << 8;
 
     /**
      * Value for {@link #flags}: {@code true} if the application is blocked via restrictions
@@ -627,15 +629,28 @@
     public String dataDir;
 
     /**
-     * Full path to the device-encrypted directory assigned to the package for
+     * Full path to the device-protected directory assigned to the package for
      * its persistent data.
+     *
+     * @see Context#createDeviceProtectedStorageContext()
      */
+    public String deviceProtectedDataDir;
+
+    /** @removed */
+    @Deprecated
     public String deviceEncryptedDataDir;
 
     /**
-     * Full path to the credential-encrypted directory assigned to the package
+     * Full path to the credential-protected directory assigned to the package
      * for its persistent data.
+     *
+     * @hide
      */
+    @SystemApi
+    public String credentialProtectedDataDir;
+
+    /** @removed */
+    @Deprecated
     public String credentialEncryptedDataDir;
 
     /**
@@ -790,8 +805,8 @@
         }
         pw.println(prefix + "dataDir=" + dataDir);
         if ((flags&DUMP_FLAG_DETAILS) != 0) {
-            pw.println(prefix + "deviceEncryptedDataDir=" + deviceEncryptedDataDir);
-            pw.println(prefix + "credentialEncryptedDataDir=" + credentialEncryptedDataDir);
+            pw.println(prefix + "deviceProtectedDataDir=" + deviceProtectedDataDir);
+            pw.println(prefix + "credentialProtectedDataDir=" + credentialProtectedDataDir);
             if (sharedLibraryFiles != null) {
                 pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
             }
@@ -889,8 +904,8 @@
         seinfo = orig.seinfo;
         sharedLibraryFiles = orig.sharedLibraryFiles;
         dataDir = orig.dataDir;
-        deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
-        credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
+        deviceEncryptedDataDir = deviceProtectedDataDir = orig.deviceProtectedDataDir;
+        credentialEncryptedDataDir = credentialProtectedDataDir = orig.credentialProtectedDataDir;
         uid = orig.uid;
         minSdkVersion = orig.minSdkVersion;
         targetSdkVersion = orig.targetSdkVersion;
@@ -944,8 +959,8 @@
         dest.writeString(seinfo);
         dest.writeStringArray(sharedLibraryFiles);
         dest.writeString(dataDir);
-        dest.writeString(deviceEncryptedDataDir);
-        dest.writeString(credentialEncryptedDataDir);
+        dest.writeString(deviceProtectedDataDir);
+        dest.writeString(credentialProtectedDataDir);
         dest.writeInt(uid);
         dest.writeString(minSdkVersion);
         dest.writeInt(targetSdkVersion);
@@ -999,8 +1014,8 @@
         seinfo = source.readString();
         sharedLibraryFiles = source.readStringArray();
         dataDir = source.readString();
-        deviceEncryptedDataDir = source.readString();
-        credentialEncryptedDataDir = source.readString();
+        deviceEncryptedDataDir = deviceProtectedDataDir = source.readString();
+        credentialEncryptedDataDir = credentialProtectedDataDir = source.readString();
         uid = source.readInt();
         minSdkVersion = source.readString();
         targetSdkVersion = source.readInt();
@@ -1056,18 +1071,18 @@
             return;
         }
 
-        deviceEncryptedDataDir = Environment
+        deviceEncryptedDataDir = deviceProtectedDataDir = Environment
                 .getDataUserDePackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
-        credentialEncryptedDataDir = Environment
+        credentialEncryptedDataDir = credentialProtectedDataDir = Environment
                 .getDataUserCePackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
 
-        if ((privateFlags & PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED) != 0
-                && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
-            dataDir = deviceEncryptedDataDir;
+        if ((privateFlags & PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0
+                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+            dataDir = deviceProtectedDataDir;
         } else {
-            dataDir = credentialEncryptedDataDir;
+            dataDir = credentialProtectedDataDir;
         }
     }
 
@@ -1134,18 +1149,19 @@
     }
 
     /** @hide */
-    public boolean isForceDeviceEncrypted() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED) != 0;
+    public boolean isDefaultToDeviceProtectedStorage() {
+        return (privateFlags
+                & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0;
     }
 
     /** @hide */
-    public boolean isEncryptionAware() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE) != 0;
+    public boolean isDirectBootAware() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE) != 0;
     }
 
     /** @hide */
-    public boolean isPartiallyEncryptionAware() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE) != 0;
+    public boolean isPartiallyDirectBootAware() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0;
     }
 
     /**
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 63a163d..5cd15dd 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -66,10 +66,14 @@
     public boolean exported = false;
 
     /**
-     * Indicate if this component is aware of encryption lifecycle, and can be
+     * Indicates if this component is aware of direct boot lifecycle, and can be
      * safely run before the user has entered their credentials (such as a lock
      * pattern or PIN).
      */
+    public boolean directBootAware = false;
+
+    /** @removed */
+    @Deprecated
     public boolean encryptionAware = false;
 
     public ComponentInfo() {
@@ -82,7 +86,7 @@
         descriptionRes = orig.descriptionRes;
         enabled = orig.enabled;
         exported = orig.exported;
-        encryptionAware = orig.encryptionAware;
+        encryptionAware = directBootAware = orig.directBootAware;
     }
 
     @Override public CharSequence loadLabel(PackageManager pm) {
@@ -160,7 +164,7 @@
             pw.println(prefix + "processName=" + processName);
         }
         pw.println(prefix + "enabled=" + enabled + " exported=" + exported
-                + " encryptionAware=" + encryptionAware);
+                + " directBootAware=" + directBootAware);
         if (descriptionRes != 0) {
             pw.println(prefix + "description=" + descriptionRes);
         }
@@ -194,7 +198,7 @@
         dest.writeInt(descriptionRes);
         dest.writeInt(enabled ? 1 : 0);
         dest.writeInt(exported ? 1 : 0);
-        dest.writeInt(encryptionAware ? 1 : 0);
+        dest.writeInt(directBootAware ? 1 : 0);
     }
     
     protected ComponentInfo(Parcel source) {
@@ -207,9 +211,9 @@
         descriptionRes = source.readInt();
         enabled = (source.readInt() != 0);
         exported = (source.readInt() != 0);
-        encryptionAware = (source.readInt() != 0);
+        encryptionAware = directBootAware = (source.readInt() != 0);
     }
-    
+
     /**
      * @hide
      */
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c684447..dabc652 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -291,6 +291,8 @@
      */
      ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
 
+    void setHomeActivity(in ComponentName className, int userId);
+
     /**
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
@@ -314,6 +316,11 @@
     int getApplicationEnabledSetting(in String packageName, int userId);
 
     /**
+     * As per {@link android.content.pm.PackageManager#flushPackageRestrictionsAsUser}.
+     */
+    void flushPackageRestrictionsAsUser(in int userId);
+
+    /**
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
      */
@@ -535,5 +542,4 @@
     boolean isPackageDeviceAdminOnAnyUser(String packageName);
 
     List<String> getPreviousCodePaths(in String packageName);
-
 }
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index 44bdf4e..cbeed35 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -62,9 +62,9 @@
     public String dataDir;
 
     /** {@hide} */
-    public String deviceEncryptedDataDir;
+    public String deviceProtectedDataDir;
     /** {@hide} */
-    public String credentialEncryptedDataDir;
+    public String credentialProtectedDataDir;
 
     /**
      * Full path to the directory where the native JNI libraries are stored.
@@ -92,8 +92,8 @@
         splitSourceDirs = orig.splitSourceDirs;
         splitPublicSourceDirs = orig.splitPublicSourceDirs;
         dataDir = orig.dataDir;
-        deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
-        credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
+        deviceProtectedDataDir = orig.deviceProtectedDataDir;
+        credentialProtectedDataDir = orig.credentialProtectedDataDir;
         nativeLibraryDir = orig.nativeLibraryDir;
         handleProfiling = orig.handleProfiling;
         functionalTest = orig.functionalTest;
@@ -117,8 +117,8 @@
         dest.writeStringArray(splitSourceDirs);
         dest.writeStringArray(splitPublicSourceDirs);
         dest.writeString(dataDir);
-        dest.writeString(deviceEncryptedDataDir);
-        dest.writeString(credentialEncryptedDataDir);
+        dest.writeString(deviceProtectedDataDir);
+        dest.writeString(credentialProtectedDataDir);
         dest.writeString(nativeLibraryDir);
         dest.writeInt((handleProfiling == false) ? 0 : 1);
         dest.writeInt((functionalTest == false) ? 0 : 1);
@@ -142,8 +142,8 @@
         splitSourceDirs = source.readStringArray();
         splitPublicSourceDirs = source.readStringArray();
         dataDir = source.readString();
-        deviceEncryptedDataDir = source.readString();
-        credentialEncryptedDataDir = source.readString();
+        deviceProtectedDataDir = source.readString();
+        credentialProtectedDataDir = source.readString();
         nativeLibraryDir = source.readString();
         handleProfiling = source.readInt() != 0;
         functionalTest = source.readInt() != 0;
@@ -157,8 +157,8 @@
         ai.splitSourceDirs = splitSourceDirs;
         ai.splitPublicSourceDirs = splitPublicSourceDirs;
         ai.dataDir = dataDir;
-        ai.deviceEncryptedDataDir = deviceEncryptedDataDir;
-        ai.credentialEncryptedDataDir = credentialEncryptedDataDir;
+        ai.deviceProtectedDataDir = deviceProtectedDataDir;
+        ai.credentialProtectedDataDir = credentialProtectedDataDir;
         ai.nativeLibraryDir = nativeLibraryDir;
     }
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8724d5e..d865f34 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -160,7 +160,8 @@
          * as defined in {@link #hasShortcutHostPermission()}, will receive it.
          *
          * @param packageName The name of the package that has the shortcuts.
-         * @param shortcuts all shortcuts from the package (dynamic and/or pinned).
+         * @param shortcuts all shortcuts from the package (dynamic and/or pinned).  Only "key"
+         *    information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}.
          * @param user The UserHandle of the profile that generated the change.
          */
         public void onShortcutsChanged(@NonNull String packageName,
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 6f2786a..ed8143e 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -37,7 +37,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.util.ExceptionUtils;
-import android.util.Log;
 
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -47,7 +46,6 @@
 import java.io.OutputStream;
 import java.security.MessageDigest;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -393,13 +391,6 @@
      * Return list of all known install sessions, regardless of the installer.
      */
     public @NonNull List<SessionInfo> getAllSessions() {
-        final ApplicationInfo info = mContext.getApplicationInfo();
-        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400110) {
-            Log.d(TAG, "Ignoring callback request from old prebuilt");
-            return Collections.EMPTY_LIST;
-        }
-
         try {
             return mInstaller.getAllSessions(mUserId).getList();
         } catch (RemoteException e) {
@@ -597,14 +588,6 @@
      *            calling thread.
      */
     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
-        // TODO: remove this temporary guard once we have new prebuilts
-        final ApplicationInfo info = mContext.getApplicationInfo();
-        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400110) {
-            Log.d(TAG, "Ignoring callback request from old prebuilt");
-            return;
-        }
-
         synchronized (mDelegates) {
             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                     handler.getLooper());
@@ -1074,8 +1057,13 @@
         }
 
         /** {@hide} */
-        public void setInstallFlagsDontKillApp() {
-            installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+        @SystemApi
+        public void setDontKillApp(boolean dontKillApp) {
+            if (dontKillApp) {
+                installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+            } else {
+                installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP;
+            }
         }
 
         /** {@hide} */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c1017fb..e89cbd7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -48,6 +48,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.storage.VolumeInfo;
 import android.util.AndroidException;
 import android.util.Log;
@@ -69,7 +70,7 @@
     private static final String TAG = "PackageManager";
 
     /** {@hide} */
-    public static final boolean APPLY_FORCE_DEVICE_ENCRYPTED = true;
+    public static final boolean APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = true;
 
     /**
      * This exception is thrown when a given package, application, or component
@@ -154,9 +155,8 @@
             MATCH_DEFAULT_ONLY,
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
-            MATCH_ENCRYPTION_AWARE,
-            MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-            MATCH_ENCRYPTION_UNAWARE,
+            MATCH_DIRECT_BOOT_AWARE,
+            MATCH_DIRECT_BOOT_UNAWARE,
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
     })
@@ -173,9 +173,8 @@
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
             MATCH_DEFAULT_ONLY,
-            MATCH_ENCRYPTION_AWARE,
-            MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-            MATCH_ENCRYPTION_UNAWARE,
+            MATCH_DIRECT_BOOT_AWARE,
+            MATCH_DIRECT_BOOT_UNAWARE,
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
     })
@@ -365,21 +364,47 @@
     public static final int MATCH_ALL = 0x00020000;
 
     /**
-     * Querying flag: include only components which are encryption unaware in
+     * Querying flag: match components which are direct boot <em>unaware</em> in
      * the returned info, regardless of the current user state.
+     * <p>
+     * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
+     * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
+     * to match only runnable components based on the user state. For example,
+     * when a user is started but credentials have not been presented yet, the
+     * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
+     * components are returned. Once the user credentials have been presented,
+     * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
+     * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
+     *
+     * @see UserManager#isUserUnlocked()
      */
+    public static final int MATCH_DIRECT_BOOT_UNAWARE = 0x00040000;
+
+    /**
+     * Querying flag: match components which are direct boot <em>aware</em> in
+     * the returned info, regardless of the current user state.
+     * <p>
+     * When neither {@link #MATCH_DIRECT_BOOT_AWARE} nor
+     * {@link #MATCH_DIRECT_BOOT_UNAWARE} are specified, the default behavior is
+     * to match only runnable components based on the user state. For example,
+     * when a user is started but credentials have not been presented yet, the
+     * user is running "locked" and only {@link #MATCH_DIRECT_BOOT_AWARE}
+     * components are returned. Once the user credentials have been presented,
+     * the user is running "unlocked" and both {@link #MATCH_DIRECT_BOOT_AWARE}
+     * and {@link #MATCH_DIRECT_BOOT_UNAWARE} components are returned.
+     *
+     * @see UserManager#isUserUnlocked()
+     */
+    public static final int MATCH_DIRECT_BOOT_AWARE = 0x00080000;
+
+    /** @removed */
+    @Deprecated
     public static final int MATCH_ENCRYPTION_UNAWARE = 0x00040000;
-
-    /**
-     * Querying flag: include only components which are encryption aware in the
-     * returned info, regardless of the current user state.
-     */
+    /** @removed */
+    @Deprecated
     public static final int MATCH_ENCRYPTION_AWARE = 0x00080000;
-
-    /**
-     * Querying flag: include both encryption aware and unaware components in
-     * the returned info, regardless of the current user state.
-     */
+    /** @removed */
+    @Deprecated
     public static final int MATCH_ENCRYPTION_AWARE_AND_UNAWARE = MATCH_ENCRYPTION_AWARE
             | MATCH_ENCRYPTION_UNAWARE;
 
@@ -401,7 +426,8 @@
      * </ul>
      *
      * @see #MATCH_UNINSTALLED_PACKAGES
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @hide
      */
     public static final int MATCH_DEBUG_TRIAGED_MISSING = 0x10000000;
@@ -2567,12 +2593,15 @@
     public abstract Intent getLeanbackLaunchIntentForPackage(String packageName);
 
     /**
-     * Return an array of all of the secondary group-ids that have been assigned
-     * to a package.
+     * Return an array of all of the POSIX secondary group IDs that have been
+     * assigned to the given package.
+     * <p>
+     * Note that the same package may have different GIDs under different
+     * {@link UserHandle} on the same device.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
-     *         desired package.
-     * @return Returns an int array of the assigned gids, or null if there are
+     *            desired package.
+     * @return Returns an int array of the assigned GIDs, or null if there are
      *         none.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
@@ -2581,8 +2610,11 @@
             throws NameNotFoundException;
 
     /**
-     * Return an array of all of the secondary group-ids that have been assigned
-     * to a package.
+     * Return an array of all of the POSIX secondary group IDs that have been
+     * assigned to the given package.
+     * <p>
+     * Note that the same package may have different GIDs under different
+     * {@link UserHandle} on the same device.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
@@ -2596,6 +2628,9 @@
 
     /**
      * Return the UID associated with the given package name.
+     * <p>
+     * Note that the same package will have different UIDs under different
+     * {@link UserHandle} on the same device.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
@@ -2608,6 +2643,9 @@
 
     /**
      * Return the UID associated with the given package name.
+     * <p>
+     * Note that the same package will have different UIDs under different
+     * {@link UserHandle} on the same device.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
@@ -2622,6 +2660,9 @@
 
     /**
      * Return the UID associated with the given package name.
+     * <p>
+     * Note that the same package will have different UIDs under different
+     * {@link UserHandle} on the same device.
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
@@ -2742,21 +2783,21 @@
      * class.
      *
      * @param component The full component name (i.e.
-     * com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity
-     * class.
+     *            com.google.apps.contacts/com.google.apps.contacts.
+     *            ContactsList) of an Activity class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return An {@link ActivityInfo} containing information about the activity.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return An {@link ActivityInfo} containing information about the
+     *         activity.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2764,9 +2805,8 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -2778,21 +2818,21 @@
      * class.
      *
      * @param component The full component name (i.e.
-     * com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver
-     * class.
+     *            com.google.apps.calendar/com.google.apps.calendar.
+     *            CalendarAlarm) of a Receiver class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return An {@link ActivityInfo} containing information about the receiver.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return An {@link ActivityInfo} containing information about the
+     *         receiver.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2800,9 +2840,8 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -2810,25 +2849,24 @@
             @ComponentInfoFlags int flags) throws NameNotFoundException;
 
     /**
-     * Retrieve all of the information we know about a particular service
-     * class.
+     * Retrieve all of the information we know about a particular service class.
      *
      * @param component The full component name (i.e.
-     * com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service
-     * class.
+     *            com.google.apps.media/com.google.apps.media.
+     *            BackgroundPlayback) of a Service class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return A {@link ServiceInfo} object containing information about the service.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return A {@link ServiceInfo} object containing information about the
+     *         service.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2836,9 +2874,8 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -2850,21 +2887,21 @@
      * provider class.
      *
      * @param component The full component name (i.e.
-     * com.google.providers.media/com.google.providers.media.MediaProvider) of a
-     * ContentProvider class.
+     *            com.google.providers.media/com.google.providers.media.
+     *            MediaProvider) of a ContentProvider class.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return A {@link ProviderInfo} object containing information about the provider.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return A {@link ProviderInfo} object containing information about the
+     *         provider.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -2872,9 +2909,8 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3499,36 +3535,37 @@
     public abstract boolean hasSystemFeature(String name, int version);
 
     /**
-     * Determine the best action to perform for a given Intent.  This is how
-     * {@link Intent#resolveActivity} finds an activity if a class has not
-     * been explicitly specified.
-     *
-     * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
-     * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
-     * only flag.  You need to do so to resolve the activity in the same way
-     * that {@link android.content.Context#startActivity(Intent)} and
+     * Determine the best action to perform for a given Intent. This is how
+     * {@link Intent#resolveActivity} finds an activity if a class has not been
+     * explicitly specified.
+     * <p>
+     * <em>Note:</em> if using an implicit Intent (without an explicit
+     * ComponentName specified), be sure to consider whether to set the
+     * {@link #MATCH_DEFAULT_ONLY} only flag. You need to do so to resolve the
+     * activity in the same way that
+     * {@link android.content.Context#startActivity(Intent)} and
      * {@link android.content.Intent#resolveActivity(PackageManager)
-     * Intent.resolveActivity(PackageManager)} do.</p>
+     * Intent.resolveActivity(PackageManager)} do.
+     * </p>
      *
      * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
+     *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}.
      * @return Returns a ResolveInfo object containing the final activity intent
-     *         that was determined to be the best action.  Returns null if no
+     *         that was determined to be the best action. Returns null if no
      *         matching activity was found. If multiple matching activities are
      *         found and there is no default set, returns a ResolveInfo object
      *         containing something else, such as the activity resolver.
-     *
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3536,46 +3573,46 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
     public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);
 
     /**
-     * Determine the best action to perform for a given Intent for a given user. This
-     * is how {@link Intent#resolveActivity} finds an activity if a class has not
-     * been explicitly specified.
-     *
-     * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
-     * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
-     * only flag.  You need to do so to resolve the activity in the same way
-     * that {@link android.content.Context#startActivity(Intent)} and
+     * Determine the best action to perform for a given Intent for a given user.
+     * This is how {@link Intent#resolveActivity} finds an activity if a class
+     * has not been explicitly specified.
+     * <p>
+     * <em>Note:</em> if using an implicit Intent (without an explicit
+     * ComponentName specified), be sure to consider whether to set the
+     * {@link #MATCH_DEFAULT_ONLY} only flag. You need to do so to resolve the
+     * activity in the same way that
+     * {@link android.content.Context#startActivity(Intent)} and
      * {@link android.content.Intent#resolveActivity(PackageManager)
-     * Intent.resolveActivity(PackageManager)} do.</p>
+     * Intent.resolveActivity(PackageManager)} do.
+     * </p>
      *
      * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
+     *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}.
      * @param userId The user id.
-     *
      * @return Returns a ResolveInfo object containing the final activity intent
-     *         that was determined to be the best action.  Returns null if no
+     *         that was determined to be the best action. Returns null if no
      *         matching activity was found. If multiple matching activities are
      *         found and there is no default set, returns a ResolveInfo object
      *         containing something else, such as the activity resolver.
-     *
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3583,12 +3620,10 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract ResolveInfo resolveActivityAsUser(Intent intent, @ResolveInfoFlags int flags,
@@ -3599,22 +3634,22 @@
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *         Or, set {@link #MATCH_ALL} to prevent any filtering of the results.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching activity, ordered from best to worst. In other words, the
-     *         first item is what would be returned by {@link #resolveActivity}.
-     *         If there are no matching activities, an empty list is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}. Or, set
+     *            {@link #MATCH_ALL} to prevent any filtering of the results.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching activity, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveActivity}. If there are no matching activities, an
+     *         empty list is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3622,9 +3657,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3632,26 +3666,27 @@
             @ResolveInfoFlags int flags);
 
     /**
-     * Retrieve all activities that can be performed for the given intent, for a specific user.
+     * Retrieve all activities that can be performed for the given intent, for a
+     * specific user.
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *         Or, set {@link #MATCH_ALL} to prevent any filtering of the results.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching activity, ordered from best to worst. In other words, the
-     *         first item is what would be returned by {@link #resolveActivity}.
-     *         If there are no matching activities, an empty list is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}. Or, set
+     *            {@link #MATCH_ALL} to prevent any filtering of the results.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching activity, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveActivity}. If there are no matching activities, an
+     *         empty list is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3659,12 +3694,10 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@@ -3672,36 +3705,35 @@
 
     /**
      * Retrieve a set of activities that should be presented to the user as
-     * similar options.  This is like {@link #queryIntentActivities}, except it
+     * similar options. This is like {@link #queryIntentActivities}, except it
      * also allows you to supply a list of more explicit Intents that you would
      * like to resolve to particular options, and takes care of returning the
      * final ResolveInfo list in a reasonable order, with no duplicates, based
      * on those inputs.
      *
-     * @param caller The class name of the activity that is making the
-     *               request.  This activity will never appear in the output
-     *               list.  Can be null.
-     * @param specifics An array of Intents that should be resolved to the
-     *                  first specific results.  Can be null.
+     * @param caller The class name of the activity that is making the request.
+     *            This activity will never appear in the output list. Can be
+     *            null.
+     * @param specifics An array of Intents that should be resolved to the first
+     *            specific results. Can be null.
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned. The most important is
-     *         {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
-     *         those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching activity. The list is ordered first by all of the intents resolved
-     *         in <var>specifics</var> and then any additional activities that
-     *         can handle <var>intent</var> but did not get included by one of
-     *         the <var>specifics</var> intents.  If there are no matching
-     *         activities, an empty list is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned. The most important is {@link #MATCH_DEFAULT_ONLY},
+     *            to limit the resolution to only those activities that support
+     *            the {@link android.content.Intent#CATEGORY_DEFAULT}.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching activity. The list is ordered first by all of the
+     *         intents resolved in <var>specifics</var> and then any additional
+     *         activities that can handle <var>intent</var> but did not get
+     *         included by one of the <var>specifics</var> intents. If there are
+     *         no matching activities, an empty list is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3709,9 +3741,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3723,18 +3754,17 @@
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching receiver, ordered from best to worst. If there are no matching
-     *         receivers, an empty list or null is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching receiver, ordered from best to worst. If there are
+     *         no matching receivers, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3742,9 +3772,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3752,24 +3781,23 @@
             @ResolveInfoFlags int flags);
 
     /**
-     * Retrieve all receivers that can handle a broadcast of the given intent, for a specific
-     * user.
+     * Retrieve all receivers that can handle a broadcast of the given intent,
+     * for a specific user.
      *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userHandle UserHandle of the user being queried.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching receiver, ordered from best to worst. If there are no matching
-     *         receivers, an empty list or null is returned.
-     *
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching receiver, ordered from best to worst. If there are
+     *         no matching receivers, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3777,12 +3805,10 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     @SystemApi
@@ -3810,20 +3836,19 @@
      * Determine the best service to handle for a given Intent.
      *
      * @param intent An intent containing all of the desired specification
-     *               (action, data, type, category, and/or component).
+     *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @return Returns a ResolveInfo object containing the final service intent
-     *         that was determined to be the best action.  Returns null if no
+     *         that was determined to be the best action. Returns null if no
      *         matching service was found.
-     *
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3831,9 +3856,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3844,19 +3868,19 @@
      *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching service, ordered from best to worst. In other words, the first
-     *         item is what would be returned by {@link #resolveService}. If there are
-     *         no matching services, an empty list or null is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching service, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveService}. If there are no matching services, an
+     *         empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3864,9 +3888,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3878,20 +3901,20 @@
      *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userId The user id.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching service, ordered from best to worst. In other words, the first
-     *         item is what would be returned by {@link #resolveService}. If there are
-     *         no matching services, an empty list or null is returned.
-     *
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching service, ordered from best to worst. In other
+     *         words, the first item is what would be returned by
+     *         {@link #resolveService}. If there are no matching services, an
+     *         empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3899,12 +3922,10 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
@@ -3916,19 +3937,18 @@
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userId The user id.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching provider, ordered from best to worst. If there are no
-     *         matching services, an empty list or null is returned.
-     *
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching provider, ordered from best to worst. If there are
+     *         no matching services, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3936,12 +3956,10 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentContentProvidersAsUser(
@@ -3953,18 +3971,17 @@
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
-     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
-     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
-     *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
-     *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return Returns a List of ResolveInfo objects containing one entry for each
-     *         matching provider, ordered from best to worst. If there are no
-     *         matching services, an empty list or null is returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+     *            {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return Returns a List of ResolveInfo objects containing one entry for
+     *         each matching provider, ordered from best to worst. If there are
+     *         no matching services, an empty list or null is returned.
      * @see #GET_META_DATA
      * @see #GET_RESOLVED_FILTER
      * @see #GET_SHARED_LIBRARY_FILES
@@ -3972,9 +3989,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_DEFAULT_ONLY
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -3986,17 +4002,16 @@
      *
      * @param name The name of the provider to find.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
-     * @return A {@link ProviderInfo} object containing information about the provider.
-     *         If a provider was not found, returns null.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
+     * @return A {@link ProviderInfo} object containing information about the
+     *         provider. If a provider was not found, returns null.
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -4004,9 +4019,8 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -4018,18 +4032,17 @@
      *
      * @param name The name of the provider to find.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @param userId The user id.
-     *
-     * @return A {@link ProviderInfo} object containing information about the provider.
-     *         If a provider was not found, returns null.
-     *
+     * @return A {@link ProviderInfo} object containing information about the
+     *         provider. If a provider was not found, returns null.
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -4037,12 +4050,10 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
-     *
      * @hide
      */
     public abstract ProviderInfo resolveContentProviderAsUser(String name,
@@ -4050,29 +4061,28 @@
 
     /**
      * Retrieve content provider information.
-     *
-     * <p><em>Note: unlike most other methods, an empty result set is indicated
+     * <p>
+     * <em>Note: unlike most other methods, an empty result set is indicated
      * by a null return instead of an empty list.</em>
      *
      * @param processName If non-null, limits the returned providers to only
-     *                    those that are hosted by the given process.  If null,
-     *                    all content providers are returned.
+     *            those that are hosted by the given process. If null, all
+     *            content providers are returned.
      * @param uid If <var>processName</var> is non-null, this is the required
-     *        uid owning the requested content providers.
+     *            uid owning the requested content providers.
      * @param flags Additional option flags. Use any combination of
-     *         {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
-     *         {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
-     *         {@link #MATCH_DISABLED_COMPONENTS},  {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
-     *         {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
-     *         {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
-     *         {@link #MATCH_UNINSTALLED_PACKAGES}
-     *         to modify the data returned.
-     *
+     *            {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+     *            {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+     *            {@link #MATCH_DISABLED_COMPONENTS},
+     *            {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *            {@link #MATCH_DIRECT_BOOT_AWARE},
+     *            {@link #MATCH_DIRECT_BOOT_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+     *            or {@link #MATCH_UNINSTALLED_PACKAGES} to modify the data
+     *            returned.
      * @return A list of {@link ProviderInfo} objects containing one entry for
      *         each provider either matching <var>processName</var> or, if
      *         <var>processName</var> is null, all known content providers.
      *         <em>If there are no matching providers, null is returned.</em>
-     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #MATCH_ALL
@@ -4080,9 +4090,8 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
-     * @see #MATCH_ENCRYPTION_AWARE
-     * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-     * @see #MATCH_ENCRYPTION_UNAWARE
+     * @see #MATCH_DIRECT_BOOT_AWARE
+     * @see #MATCH_DIRECT_BOOT_UNAWARE
      * @see #MATCH_SYSTEM_ONLY
      * @see #MATCH_UNINSTALLED_PACKAGES
      */
@@ -4618,13 +4627,13 @@
         final PackageParser parser = new PackageParser();
         final File apkFile = new File(archiveFilePath);
         try {
-            if ((flags & (MATCH_ENCRYPTION_UNAWARE | MATCH_ENCRYPTION_AWARE)) != 0) {
+            if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
                 // Caller expressed an explicit opinion about what encryption
                 // aware/unaware components they want to see, so fall through and
                 // give them what they want
             } else {
                 // Caller expressed no opinion, so match everything
-                flags |= MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+                flags |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
             }
 
             PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0);
@@ -5225,7 +5234,6 @@
     public abstract void setComponentEnabledSetting(ComponentName componentName,
             int newState, int flags);
 
-
     /**
      * Return the enabled setting for a package component (activity,
      * receiver, service, provider).  This returns the last value set by
@@ -5283,6 +5291,16 @@
     public abstract int getApplicationEnabledSetting(String packageName);
 
     /**
+     * Flush the package restrictions for a given user to disk. This forces the package restrictions
+     * like component and package enabled settings to be written to disk and avoids the delay that
+     * is otherwise present when changing those settings.
+     *
+     * @param userId Ther userId of the user whose restrictions are to be flushed.
+     * @hide
+     */
+    public abstract void flushPackageRestrictionsAsUser(int userId);
+
+    /**
      * Puts the package in a hidden state, which is almost like an uninstalled state,
      * making the package unavailable, but it doesn't remove the data or the actual
      * package file. Application can be unhidden by either resetting the hidden state
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7d7be9a..db7ca2a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2865,13 +2865,13 @@
             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
         }
 
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_forceDeviceEncrypted, false)
-                && (flags & PARSE_IS_SYSTEM) != 0) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED;
+        if (sa.getBoolean(R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
+                false) && (flags & PARSE_IS_SYSTEM) != 0) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
         }
-        if (sa.getBoolean(R.styleable.AndroidManifestApplication_encryptionAware, false)
+        if (sa.getBoolean(R.styleable.AndroidManifestApplication_directBootAware, false)
                 && (flags & PARSE_IS_SYSTEM) != 0) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE;
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
         }
 
         if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity,
@@ -3493,9 +3493,9 @@
             a.info.lockTaskLaunchMode =
                     sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
 
-            a.info.encryptionAware = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_encryptionAware,
-                    owner.applicationInfo.isEncryptionAware());
+            a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_directBootAware,
+                    owner.applicationInfo.isDirectBootAware());
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
@@ -3511,14 +3511,14 @@
                 }
             }
 
-            a.info.encryptionAware = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_encryptionAware,
-                    owner.applicationInfo.isEncryptionAware());
+            a.info.encryptionAware = a.info.directBootAware = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_directBootAware,
+                    owner.applicationInfo.isDirectBootAware());
         }
 
-        if (a.info.encryptionAware) {
+        if (a.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
-                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE;
+                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
         sa.recycle();
@@ -3732,7 +3732,7 @@
         info.maxRecents = target.info.maxRecents;
         info.layout = target.info.layout;
         info.resizeMode = target.info.resizeMode;
-        info.encryptionAware = target.info.encryptionAware;
+        info.encryptionAware = info.directBootAware = target.info.directBootAware;
 
         Activity a = new Activity(mParseActivityAliasArgs, info);
         if (outError[0] != null) {
@@ -3921,12 +3921,12 @@
             }
         }
 
-        p.info.encryptionAware = sa.getBoolean(
-                R.styleable.AndroidManifestProvider_encryptionAware,
-                owner.applicationInfo.isEncryptionAware());
-        if (p.info.encryptionAware) {
+        p.info.encryptionAware = p.info.directBootAware = sa.getBoolean(
+                R.styleable.AndroidManifestProvider_directBootAware,
+                owner.applicationInfo.isDirectBootAware());
+        if (p.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
-                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE;
+                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
         sa.recycle();
@@ -4213,12 +4213,12 @@
             }
         }
 
-        s.info.encryptionAware = sa.getBoolean(
-                R.styleable.AndroidManifestService_encryptionAware,
-                owner.applicationInfo.isEncryptionAware());
-        if (s.info.encryptionAware) {
+        s.info.encryptionAware = s.info.directBootAware = sa.getBoolean(
+                R.styleable.AndroidManifestService_directBootAware,
+                owner.applicationInfo.isDirectBootAware());
+        if (s.info.directBootAware) {
             owner.applicationInfo.privateFlags |=
-                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE;
+                    ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
         }
 
         sa.recycle();
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 38e0044..e85311d 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -23,8 +23,8 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
 import android.util.ArraySet;
@@ -98,10 +98,10 @@
             }
         }
 
-        final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
-                && !componentInfo.encryptionAware;
-        final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
-                && componentInfo.encryptionAware;
+        final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
+                && !componentInfo.directBootAware;
+        final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
+                && componentInfo.directBootAware;
         return matchesUnaware || matchesAware;
     }
 
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index bb28bde..6162d1a 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -365,7 +365,8 @@
     protected List<ResolveInfo> queryIntentServices(int userId) {
         final PackageManager pm = mContext.getPackageManager();
         return pm.queryIntentServicesAsUser(new Intent(mInterfaceName),
-                PackageManager.GET_META_DATA | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                 userId);
     }
 
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index e41136c..ae75e3f 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -46,8 +46,6 @@
  *   if necessary, and persisted.
  *
  *   We will disallow byte[] icons, because they can easily go over binder size limit.
- *
- * TODO Move save/load to this class
  */
 public class ShortcutInfo implements Parcelable {
     /* @hide */
@@ -524,7 +522,7 @@
     }
 
     /** @hide*/
-    public void setFlags(@ShortcutFlags int flags) {
+    public void replaceFlags(@ShortcutFlags int flags) {
         mFlags = flags;
     }
 
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index c4afbfb..b75e653 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -54,10 +54,9 @@
     private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
+    private static final Object sLock = new Object();
     private static boolean sSensorModuleInitialized = false;
-    private static InjectEventQueue mInjectEventQueue = null;
-
-    private final Object mLock = new Object();
+    private static InjectEventQueue sInjectEventQueue = null;
 
     private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
     private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
@@ -84,24 +83,24 @@
 
     /** {@hide} */
     public SystemSensorManager(Context context, Looper mainLooper) {
+        synchronized(sLock) {
+            if (!sSensorModuleInitialized) {
+                sSensorModuleInitialized = true;
+                nativeClassInit();
+            }
+        }
+
         mMainLooper = mainLooper;
         mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
         mContext = context;
         mNativeInstance = nativeCreate(context.getOpPackageName());
 
-        synchronized(mLock) {
-            if (!sSensorModuleInitialized) {
-                sSensorModuleInitialized = true;
-                nativeClassInit();
-            }
-
-            // initialize the sensor list
-            for (int index = 0;;++index) {
-                Sensor sensor = new Sensor();
-                if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
-                mFullSensorsList.add(sensor);
-                mHandleToSensor.put(sensor.getHandle(), sensor);
-            }
+        // initialize the sensor list
+        for (int index = 0;;++index) {
+            Sensor sensor = new Sensor();
+            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
+            mFullSensorsList.add(sensor);
+            mHandleToSensor.put(sensor.getHandle(), sensor);
         }
     }
 
@@ -257,7 +256,7 @@
     }
 
     protected boolean initDataInjectionImpl(boolean enable) {
-        synchronized (mLock) {
+        synchronized (sLock) {
             if (enable) {
                 boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance);
                 // The HAL does not support injection OR SensorService hasn't been set in DI mode.
@@ -266,15 +265,15 @@
                     return false;
                 }
                 // Initialize a client for data_injection.
-                if (mInjectEventQueue == null) {
-                    mInjectEventQueue = new InjectEventQueue(mMainLooper, this,
+                if (sInjectEventQueue == null) {
+                    sInjectEventQueue = new InjectEventQueue(mMainLooper, this,
                             mContext.getPackageName());
                 }
             } else {
                 // If data injection is being disabled clean up the native resources.
-                if (mInjectEventQueue != null) {
-                    mInjectEventQueue.dispose();
-                    mInjectEventQueue = null;
+                if (sInjectEventQueue != null) {
+                    sInjectEventQueue.dispose();
+                    sInjectEventQueue = null;
                 }
             }
             return true;
@@ -283,17 +282,17 @@
 
     protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
             long timestamp) {
-        synchronized (mLock) {
-            if (mInjectEventQueue == null) {
+        synchronized (sLock) {
+            if (sInjectEventQueue == null) {
                 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
                 return false;
             }
-            int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
+            int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
                                                          timestamp);
             // If there are any errors in data injection clean up the native resources.
             if (ret != 0) {
-                mInjectEventQueue.dispose();
-                mInjectEventQueue = null;
+                sInjectEventQueue.dispose();
+                sInjectEventQueue = null;
             }
             return ret == 0;
         }
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 04e64af..ffd9d89 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1099,6 +1099,11 @@
                 if (oldHandler == null) {
                     updateCallbackLocked(callback, handler);
                 }
+
+                // If not connected to camera service, schedule a reconnect to camera service.
+                if (mCameraService == null) {
+                    scheduleCameraServiceReconnectionLocked();
+                }
             }
         }
 
@@ -1123,6 +1128,11 @@
                 if (oldHandler == null) {
                     updateTorchCallbackLocked(callback, handler);
                 }
+
+                // If not connected to camera service, schedule a reconnect to camera service.
+                if (mCameraService == null) {
+                    scheduleCameraServiceReconnectionLocked();
+                }
             }
         }
 
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 6cc7fec..dfa19b0 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -1196,7 +1196,7 @@
      *
      * <p>In particular these formats are converted:
      * <ul>
-     * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF
+     * <li>ImageFormat.JPEG => HAL_DATASPACE_V0_JFIF
      * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
      * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
      * <li>others => HAL_DATASPACE_UNKNOWN
@@ -1223,7 +1223,7 @@
     static int imageFormatToDataspace(int format) {
         switch (format) {
             case ImageFormat.JPEG:
-                return HAL_DATASPACE_JFIF;
+                return HAL_DATASPACE_V0_JFIF;
             case ImageFormat.DEPTH_POINT_CLOUD:
             case ImageFormat.DEPTH16:
                 return HAL_DATASPACE_DEPTH;
@@ -1633,8 +1633,16 @@
     private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
 
 
+    private static final int HAL_DATASPACE_STANDARD_SHIFT = 16;
+    private static final int HAL_DATASPACE_TRANSFER_SHIFT = 22;
+    private static final int HAL_DATASPACE_RANGE_SHIFT = 27;
+
     private static final int HAL_DATASPACE_UNKNOWN = 0x0;
-    private static final int HAL_DATASPACE_JFIF = 0x101;
+    private static final int HAL_DATASPACE_V0_JFIF =
+            (2 << HAL_DATASPACE_STANDARD_SHIFT) |
+            (3 << HAL_DATASPACE_TRANSFER_SHIFT) |
+            (1 << HAL_DATASPACE_RANGE_SHIFT);
+
     private static final int HAL_DATASPACE_DEPTH = 0x1000;
 
     private static final long DURATION_20FPS_NS = 50000000L;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 38a760a..4ddf767 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -15,13 +15,8 @@
  */
 package android.hardware.location;
 
-import android.Manifest;
 import android.annotation.SystemApi;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.ServiceConnection;
-import android.hardware.location.ContextHubService;
-import android.hardware.location.NanoAppInstanceInfo;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -29,19 +24,11 @@
 import android.os.ServiceManager;
 import android.util.Log;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 /**
- * A class that exposes the Context hubs on a device to
- * applicaions.
+ * A class that exposes the Context hubs on a device to applications.
  *
- * Please not that this class is not expected to be used by
- * unbundled applications. Also, calling applications are
- * expected to have LOCTION_HARDWARE premissions to use this
- * class.
+ * Please note that this class is not expected to be used by unbundled applications. Also, calling
+ * applications are expected to have LOCATION_HARDWARE permissions to use this class.
  *
  * @hide
  */
@@ -49,21 +36,14 @@
 public final class ContextHubManager {
 
     private static final String TAG = "ContextHubManager";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
-    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
-            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
-    private final Context mContext;
     private final Looper mMainLooper;
     private IContextHubService mContextHubService;
-    private boolean mContextHubConnected;
-    private ContextHubCallback mCallback;
+    private Callback mCallback;
     private Handler mCallbackHandler;
 
     /**
-     * A special context hub identifer meaning any possible hub on
-     * the system.
+     * A special context hub identifier meaning any possible hub on the system.
      */
     public static final int ANY_HUB       = -1;
     /**
@@ -80,19 +60,24 @@
     public static final int MSG_DATA_SEND       = 3;
 
     /**
-     * an interface to receive asynchronous communication from the context hub
+     * An interface to receive asynchronous communication from the context hub.
      */
-    public abstract class ContextHubCallback {
+    public abstract static class Callback {
+        protected Callback() {}
+
         /**
-         * callback function called on message receipt from context hub
+         * Callback function called on message receipt from context hub.
          *
-         * @param hubId id of the hub of the message
-         * @param nanoAppId identifier for the app that sent the message
-         * @param msg the context hub message
+         * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
+         * @param nanoAppHandle Handle (unique identifier) for the app that sent the message.
+         * @param message The context hub message.
          *
          * @see ContextHubMessage
          */
-        abstract void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg);
+        public abstract void onMessageReceipt(
+                int hubHandle,
+                int nanoAppHandle,
+                ContextHubMessage message);
     }
 
     /**
@@ -104,7 +89,7 @@
         try {
             retVal = getBinder().getContextHubHandles();
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch context hub handles :" + e.toString());
+            Log.e(TAG, "Could not fetch context hub handles : " + e);
         }
         return retVal;
     }
@@ -112,25 +97,24 @@
     /**
      * Get more information about a specific hub.
      *
-     * @param contexthubHandle Handle of context hub
-     *
-     * @return ContextHubInfo  returned information about the hub
+     * @param hubHandle Handle (system-wide unique identifier) of a context hub.
+     * @return ContextHubInfo Information about the requested context hub.
      *
      * @see ContextHubInfo
      */
-    public ContextHubInfo getContextHubInfo(int contexthubHandle) {
+    public ContextHubInfo getContextHubInfo(int hubHandle) {
         ContextHubInfo retVal = null;
         try {
-            retVal = getBinder().getContextHubInfo(contexthubHandle);
+            retVal = getBinder().getContextHubInfo(hubHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch context hub info :" + e.toString());
+            Log.e(TAG, "Could not fetch context hub info :" + e);
         }
 
         return retVal;
     }
 
     /**
-     * Load a nanoapp on a specified context hub
+     * Load a nano app on a specified context hub.
      *
      * @param hubHandle handle of context hub to load the app on.
      * @param app the nanoApp to load on the hub
@@ -149,7 +133,7 @@
         try {
             retVal = getBinder().loadNanoApp(hubHandle, app);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch load nanoApp :" + e.toString());
+            Log.e(TAG, "Could not fetch load nanoApp :" + e);
         }
 
         return retVal;
@@ -158,17 +142,17 @@
     /**
      * Unload a specified nanoApp
      *
-     * @param nanoAppInstanceHandle handle of the nanoApp to load
+     * @param nanoAppHandle handle of the nanoApp to load
      *
-     * @return int  0 on success, -1 otherewise
+     * @return int  0 on success, -1 otherwise
      */
-    public int unloadNanoApp(int nanoAppInstanceHandle) {
+    public int unloadNanoApp(int nanoAppHandle) {
         int retVal = -1;
 
         try {
-            retVal = getBinder().unloadNanoApp(nanoAppInstanceHandle);
+            retVal = getBinder().unloadNanoApp(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch unload nanoApp :" + e.toString());
+            Log.e(TAG, "Could not fetch unload nanoApp :" + e);
         }
 
         return retVal;
@@ -177,20 +161,18 @@
     /**
      * get information about the nano app instance
      *
-     * @param nanoAppInstanceHandle handle of the nanoAppInstance
-     *
-     * @return NanoAppInstanceInfo Inforamtion about the nano app
-     *         instance.
+     * @param nanoAppHandle handle of the nanoAppInstance
+     * @return NanoAppInstanceInfo Information about the nano app instance.
      *
      * @see NanoAppInstanceInfo
      */
-    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) {
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
         NanoAppInstanceInfo retVal = null;
 
         try {
-            retVal = getBinder().getNanoAppInstanceInfo(nanoAppInstanceHandle);
+            retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not fetch nanoApp info :" + e.toString());
+            Log.e(TAG, "Could not fetch nanoApp info :" + e);
         }
 
         return retVal;
@@ -204,33 +186,24 @@
      *
      * @see NanoAppFilter
      *
-     * @return Integer[] Array of handles to any found nano apps
+     * @return int[] Array of handles to any found nano apps
      */
-    public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
-        int[] temp;
-        Integer[] retVal = null;
-
+    public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
+        int[] retVal = null;
         try {
-            temp = getBinder().findNanoAppOnHub(hubHandle, filter);
-            retVal = new Integer[temp.length];
-            for (int i = 0; i < temp.length; i++) {
-                retVal[i] = temp[i];
-            }
+            retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
         } catch (RemoteException e) {
-            Log.e(TAG, "Could not query nanoApp instance :" + e.toString());
+            Log.e(TAG, "Could not query nanoApp instance :" + e);
         }
-
         return retVal;
     }
 
     /**
-     * Send a message to a spcific nano app instance on a context
-     * hub
-     *
+     * Send a message to a specific nano app instance on a context hub.
      *
      * @param hubHandle handle of the hub to send the message to
      * @param nanoAppHandle  handle of the nano app to send to
-     * @param msg Message to be sent
+     * @param message Message to be sent
      *
      * @see ContextHubMessage
      *
@@ -251,29 +224,27 @@
     /**
      * Set a callback to receive messages from the context hub
      *
-     *
      * @param callback Callback object
      *
-     * @see ContextHubCallback
+     * @see Callback
      *
      * @return int 0 on success, -1 otherwise
      */
-    public int registerContextHubCallback(ContextHubCallback callback) {
-        return registerContextHubCallback(callback, null);
+    public int registerCallback(Callback callback) {
+        return registerCallback(callback, null);
     }
 
     /**
      * Set a callback to receive messages from the context hub
      *
-     *
      * @param callback Callback object
-     * @param hander Hander object
+     * @param handler Handler object
      *
-     * @see ContextHubCallback
+     * @see Callback
      *
      * @return int 0 on success, -1 otherwise
      */
-    public int registerContextHubCallback(ContextHubCallback callback, Handler handler) {
+    public int registerCallback(Callback callback, Handler handler) {
         synchronized(this) {
             if (mCallback != null) {
                 Log.e(TAG, "Max number of callbacks reached!");
@@ -286,16 +257,15 @@
     }
 
     /**
-     * Unregister a callback for receive messages from the context
-     * hub
+     * Unregister a callback for receive messages from the context hub.
      *
-     * @see ContextHubCallback
+     * @see Callback
      *
      * @param callback method to deregister
      *
      * @return int 0 on success, -1 otherwise
      */
-    public int unregisterContextHubCallback(ContextHubCallback callback) {
+    public int unregisterCallback(Callback callback) {
       synchronized(this) {
           if (callback != mCallback) {
               Log.e(TAG, "Cannot recognize callback!");
@@ -308,17 +278,13 @@
       return 0;
     }
 
-    private void checkPermissions() {
-        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
-    }
-
     private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
         @Override
         public void onMessageReceipt(final int hubId, final int nanoAppId,
-                final ContextHubMessage message) throws RemoteException {
+                final ContextHubMessage message) {
             if (mCallback != null) {
                 synchronized(this) {
-                    final ContextHubCallback callback = mCallback;
+                    final Callback callback = mCallback;
                     Handler handler = mCallbackHandler == null ?
                             new Handler(mMainLooper) : mCallbackHandler;
                     handler.post(new Runnable() {
@@ -336,8 +302,6 @@
 
     /** @hide */
     public ContextHubManager(Context context, Looper mainLooper) {
-        checkPermissions();
-        mContext = context;
         mMainLooper = mainLooper;
 
         IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
@@ -347,7 +311,7 @@
             try {
                 getBinder().registerCallback(mClientCallback);
             } catch (RemoteException e) {
-                Log.e(TAG, "Could not register callback:" + e.toString());
+                Log.e(TAG, "Could not register callback:" + e);
             }
 
         } else {
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 658d90b..274babe 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -16,10 +16,8 @@
 
 package android.hardware.location;
 
-import android.app.Service;
+import android.Manifest;
 import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -32,6 +30,9 @@
 public class ContextHubService extends IContextHubService.Stub {
 
     private static final String TAG = "ContextHubService";
+    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
     public static final String CONTEXTHUB_SERVICE = "contexthub_service";
 
@@ -56,6 +57,7 @@
 
     @Override
     public int registerCallback(IContextHubCallback callback) throws RemoteException{
+        checkPermissions();
         mCallback = callback;
         return 0;
     }
@@ -83,6 +85,7 @@
 
     @Override
     public int[] getContextHubHandles() throws RemoteException {
+        checkPermissions();
         int [] returnArray = new int[mContextHubInfo.length];
 
         for (int i = 0; i < returnArray.length; ++i) {
@@ -96,6 +99,7 @@
 
     @Override
     public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
+        checkPermissions();
         contextHubHandle -= 1;
         if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
             return null; // null means fail
@@ -106,6 +110,7 @@
 
     @Override
     public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
+        checkPermissions();
         contextHubHandle -= 1;
 
         if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
@@ -123,11 +128,12 @@
         return nativeSendMessage(msgHeader, app.getAppBinary());
     }
 
-      @Override
-      public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+    @Override
+    public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+        checkPermissions();
         NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
         if (info == null) {
-          return -1; //means failed
+            return -1; //means failed
         }
 
         // Call Native interface here
@@ -137,10 +143,12 @@
         msgHeader[2] = info.getHandle();
 
         return nativeSendMessage(msgHeader, null);
-      }
+    }
 
     @Override
-    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException {
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
+            throws RemoteException {
+        checkPermissions();
         // This assumes that all the nanoAppInfo is current. This is reasonable
         // for the use cases for tightly controlled nanoApps.
         if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
@@ -152,6 +160,7 @@
 
     @Override
     public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+        checkPermissions();
         ArrayList<Integer> foundInstances = new ArrayList<Integer>();
 
         for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
@@ -171,7 +180,9 @@
     }
 
     @Override
-    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
+    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
+            throws RemoteException {
+        checkPermissions();
         int[] msgHeader = new int[8];
         msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
         msgHeader[1] = hubHandle;
@@ -181,5 +192,9 @@
 
         return nativeSendMessage(msgHeader, msg.getData());
     }
+
+    private void checkPermissions() {
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+    }
 }
 
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 2dfb061..8582150 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -43,6 +43,16 @@
     public final RssiCurve rssiCurve;
 
     /**
+     * A boolean value that indicates whether or not the network is believed to be metered.
+     *
+     * <p>A network can be classified as metered if the user would be
+     * sensitive to heavy data usage on that connection due to monetary costs,
+     * data limitations or battery/performance issues. A typical example would
+     * be a wifi connection where the user would be charged for usage.
+     */
+    public final boolean meteredHint;
+
+    /**
      * Construct a new {@link ScoredNetwork}.
      *
      * @param networkKey the {@link NetworkKey} uniquely identifying this network.
@@ -54,8 +64,26 @@
      *     the scorer may choose to issue an out-of-band update at any time.
      */
     public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
+        this(networkKey, rssiCurve, false /* meteredHint */);
+    }
+
+    /**
+     * Construct a new {@link ScoredNetwork}.
+     *
+     * @param networkKey the {@link NetworkKey} uniquely identifying this network.
+     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
+     *     has opted not to score at this time. Passing a null value here is strongly preferred to
+     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+     *     indicates to the system not to request scores for this network in the future, although
+     *     the scorer may choose to issue an out-of-band update at any time.
+     * @param meteredHint A boolean value indicating whether or not the network is believed to be
+     *     metered.
+     */
+    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) {
         this.networkKey = networkKey;
         this.rssiCurve = rssiCurve;
+        this.meteredHint = meteredHint;
     }
 
     private ScoredNetwork(Parcel in) {
@@ -65,6 +93,7 @@
         } else {
             rssiCurve = null;
         }
+        meteredHint = in.readByte() != 0;
     }
 
     @Override
@@ -81,6 +110,7 @@
         } else {
             out.writeByte((byte) 0);
         }
+        out.writeByte((byte) (meteredHint ? 1 : 0));
     }
 
     @Override
@@ -90,18 +120,20 @@
 
         ScoredNetwork that = (ScoredNetwork) o;
 
-        return Objects.equals(networkKey, that.networkKey) &&
-                Objects.equals(rssiCurve, that.rssiCurve);
+        return Objects.equals(networkKey, that.networkKey)
+            && Objects.equals(rssiCurve, that.rssiCurve)
+            && Objects.equals(meteredHint, that.meteredHint);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(networkKey, rssiCurve);
+        return Objects.hash(networkKey, rssiCurve, meteredHint);
     }
 
     @Override
     public String toString() {
-        return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
+        return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve
+            + ",meteredHint=" + meteredHint + "]";
     }
 
     public static final Parcelable.Creator<ScoredNetwork> CREATOR =
diff --git a/core/java/android/os/BadParcelableException.java b/core/java/android/os/BadParcelableException.java
index a1c5bb2..7e0b1a5 100644
--- a/core/java/android/os/BadParcelableException.java
+++ b/core/java/android/os/BadParcelableException.java
@@ -15,11 +15,15 @@
  */
 
 package android.os;
+
 import android.util.AndroidRuntimeException;
 
 /**
- * The object you are calling has died, because its hosting process
- * no longer exists.
+ * Exception thrown when a {@link Parcelable} is malformed or otherwise invalid.
+ * <p>
+ * This is typically encountered when a custom {@link Parcelable} object is
+ * passed to another process that doesn't have the same {@link Parcelable} class
+ * in its {@link ClassLoader}.
  */
 public class BadParcelableException extends AndroidRuntimeException {
     public BadParcelableException(String msg) {
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 5c71373..6e50155 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -26,7 +26,9 @@
 import java.util.Set;
 
 /**
- * A mapping from String values to various types.
+ * A mapping from String keys to values of various types. In most cases, you
+ * should work directly with either the {@link Bundle} or
+ * {@link PersistableBundle} subclass.
  */
 public class BaseBundle {
     private static final String TAG = "Bundle";
@@ -35,6 +37,32 @@
     // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
     static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
 
+    /**
+     * Flag indicating that this Bundle is okay to "defuse." That is, it's okay
+     * for system processes to ignore any {@link BadParcelableException}
+     * encountered when unparceling it, leaving an empty bundle in its place.
+     * <p>
+     * This should <em>only</em> be set when the Bundle reaches its final
+     * destination, otherwise a system process may clobber contents that were
+     * destined for an app that could have unparceled them.
+     */
+    static final int FLAG_DEFUSABLE = 1 << 0;
+
+    private static volatile boolean sShouldDefuse = false;
+
+    /**
+     * Set global variable indicating that any Bundles parsed in this process
+     * should be "defused." That is, any {@link BadParcelableException}
+     * encountered will be suppressed and logged, leaving an empty Bundle
+     * instead of crashing.
+     *
+     * @hide
+     */
+    public static void setShouldDefuse(boolean shouldDefuse) {
+        sShouldDefuse = shouldDefuse;
+    }
+
+    /** {@hide} */
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -58,6 +86,9 @@
      */
     private ClassLoader mClassLoader;
 
+    /** {@hide} */
+    int mFlags;
+
     /**
      * Constructs a new, empty Bundle that uses a specific ClassLoader for
      * instantiating Parcelable and Serializable objects.
@@ -197,6 +228,11 @@
             return;
         }
 
+        if (sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
+            Log.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "
+                    + "clobber all data inside!", new Throwable());
+        }
+
         if (mParcelledData == EMPTY_PARCEL) {
             if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                     + ": empty");
@@ -221,9 +257,19 @@
             mMap.erase();
             mMap.ensureCapacity(N);
         }
-        mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
-        mParcelledData.recycle();
-        mParcelledData = null;
+        try {
+            mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+        } catch (BadParcelableException e) {
+            if (sShouldDefuse) {
+                Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
+                mMap.erase();
+            } else {
+                throw e;
+            }
+        } finally {
+            mParcelledData.recycle();
+            mParcelledData = null;
+        }
         if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                 + " final map: " + mMap);
     }
@@ -1371,9 +1417,8 @@
             return;
         }
 
-        int magic = parcel.readInt();
+        final int magic = parcel.readInt();
         if (magic != BUNDLE_MAGIC) {
-            //noinspection ThrowableInstanceNeverThrown
             throw new IllegalStateException("Bad magic number for Bundle: 0x"
                     + Integer.toHexString(magic));
         }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e1c7ad77..6df2a9d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -477,10 +477,10 @@
          * also be bumped.
          */
         static final String[] USER_ACTIVITY_TYPES = {
-            "other", "button", "touch"
+            "other", "button", "touch", "accessibility"
         };
         
-        public static final int NUM_USER_ACTIVITY_TYPES = 3;
+        public static final int NUM_USER_ACTIVITY_TYPES = 4;
 
         public abstract void noteUserActivityLocked(int type);
         public abstract boolean hasUserActivity();
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 74699fd..05dd48b 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -27,11 +27,17 @@
 import java.util.List;
 
 /**
- * A mapping from String values to various Parcelable types.
+ * A mapping from String keys to various {@link Parcelable} values.
  *
+ * @see PersistableBundle
  */
 public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
+    private static final int FLAG_HAS_FDS = 1 << 8;
+    private static final int FLAG_HAS_FDS_KNOWN = 1 << 9;
+    private static final int FLAG_ALLOW_FDS = 1 << 10;
+
     public static final Bundle EMPTY;
+
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -40,15 +46,12 @@
         EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL;
     }
 
-    private boolean mHasFds = false;
-    private boolean mFdsKnown = true;
-    private boolean mAllowFds = true;
-
     /**
      * Constructs a new, empty Bundle.
      */
     public Bundle() {
         super();
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -59,16 +62,18 @@
      */
     Bundle(Parcel parcelledData) {
         super(parcelledData);
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     /* package */ Bundle(Parcel parcelledData, int length) {
         super(parcelledData, length);
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     /**
@@ -80,6 +85,7 @@
      */
     public Bundle(ClassLoader loader) {
         super(loader);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -90,6 +96,7 @@
      */
     public Bundle(int capacity) {
         super(capacity);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -100,9 +107,7 @@
      */
     public Bundle(Bundle b) {
         super(b);
-
-        mHasFds = b.mHasFds;
-        mFdsKnown = b.mFdsKnown;
+        mFlags = b.mFlags;
     }
 
     /**
@@ -113,6 +118,7 @@
      */
     public Bundle(PersistableBundle b) {
         super(b);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -145,14 +151,45 @@
         return super.getClassLoader();
     }
 
-    /** @hide */
+    /** {@hide} */
     public boolean setAllowFds(boolean allowFds) {
-        boolean orig = mAllowFds;
-        mAllowFds = allowFds;
+        final boolean orig = (mFlags & FLAG_ALLOW_FDS) != 0;
+        if (allowFds) {
+            mFlags |= FLAG_ALLOW_FDS;
+        } else {
+            mFlags &= ~FLAG_ALLOW_FDS;
+        }
         return orig;
     }
 
     /**
+     * Mark if this Bundle is okay to "defuse." That is, it's okay for system
+     * processes to ignore any {@link BadParcelableException} encountered when
+     * unparceling it, leaving an empty bundle in its place.
+     * <p>
+     * This should <em>only</em> be set when the Bundle reaches its final
+     * destination, otherwise a system process may clobber contents that were
+     * destined for an app that could have unparceled them.
+     *
+     * @hide
+     */
+    public void setDefusable(boolean defusable) {
+        if (defusable) {
+            mFlags |= FLAG_DEFUSABLE;
+        } else {
+            mFlags &= ~FLAG_DEFUSABLE;
+        }
+    }
+
+    /** {@hide} */
+    public static Bundle setDefusable(Bundle bundle, boolean defusable) {
+        if (bundle != null) {
+            bundle.setDefusable(defusable);
+        }
+        return bundle;
+    }
+
+    /**
      * Clones the current Bundle. The internal map is cloned, but the keys and
      * values to which it refers are copied by reference.
      */
@@ -167,9 +204,7 @@
     @Override
     public void clear() {
         super.clear();
-
-        mHasFds = false;
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -182,16 +217,20 @@
         bundle.unparcel();
         mMap.putAll(bundle.mMap);
 
-        // fd state is now known if and only if both bundles already knew
-        mHasFds |= bundle.mHasFds;
-        mFdsKnown = mFdsKnown && bundle.mFdsKnown;
+        // FD state is now known if and only if both bundles already knew
+        if ((bundle.mFlags & FLAG_HAS_FDS) != 0) {
+            mFlags |= FLAG_HAS_FDS;
+        }
+        if ((bundle.mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
+            mFlags &= ~FLAG_HAS_FDS_KNOWN;
+        }
     }
 
     /**
      * Reports whether the bundle contains any parcelled file descriptors.
      */
     public boolean hasFileDescriptors() {
-        if (!mFdsKnown) {
+        if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
             boolean fdFound = false;    // keep going until we find one or run out of data
 
             if (mParcelledData != null) {
@@ -247,10 +286,12 @@
                 }
             }
 
-            mHasFds = fdFound;
-            mFdsKnown = true;
+            if (fdFound) {
+                mFlags |= FLAG_HAS_FDS;
+            }
+            mFlags |= FLAG_HAS_FDS_KNOWN;
         }
-        return mHasFds;
+        return (mFlags & FLAG_HAS_FDS) != 0;
     }
 
     /**
@@ -346,7 +387,7 @@
     public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -384,7 +425,7 @@
     public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -399,14 +440,14 @@
             @Nullable ArrayList<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /** {@hide} */
     public void putParcelableList(String key, List<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -421,7 +462,7 @@
             @Nullable SparseArray<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -1074,7 +1115,7 @@
      */
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
+        final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0);
         try {
             super.writeToParcelInner(parcel, flags);
         } finally {
@@ -1089,8 +1130,10 @@
      */
     public void readFromParcel(Parcel parcel) {
         super.readFromParcelInner(parcel);
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     @Override
@@ -1105,5 +1148,4 @@
         }
         return "Bundle[" + mMap.toString() + "]";
     }
-
 }
diff --git a/core/java/android/os/DeadSystemException.java b/core/java/android/os/DeadSystemException.java
index 595365c..8fb53e2 100644
--- a/core/java/android/os/DeadSystemException.java
+++ b/core/java/android/os/DeadSystemException.java
@@ -18,7 +18,7 @@
 
 /**
  * The core Android system has died and is going through a runtime restart. All
- * running apps will be promptly be killed.
+ * running apps will be promptly killed.
  */
 public class DeadSystemException extends DeadObjectException {
     public DeadSystemException() {
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 307bd2d..f6e8940 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -34,6 +34,7 @@
     private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE";
     private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
     private static final String ENV_ANDROID_DATA = "ANDROID_DATA";
+    private static final String ENV_ANDROID_EXPAND = "ANDROID_EXPAND";
     private static final String ENV_ANDROID_STORAGE = "ANDROID_STORAGE";
     private static final String ENV_DOWNLOAD_CACHE = "DOWNLOAD_CACHE";
     private static final String ENV_OEM_ROOT = "OEM_ROOT";
@@ -54,6 +55,7 @@
 
     private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
     private static final File DIR_ANDROID_DATA = getDirectory(ENV_ANDROID_DATA, "/data");
+    private static final File DIR_ANDROID_EXPAND = getDirectory(ENV_ANDROID_EXPAND, "/mnt/expand");
     private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
     private static final File DIR_DOWNLOAD_CACHE = getDirectory(ENV_DOWNLOAD_CACHE, "/cache");
     private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
@@ -229,6 +231,11 @@
     }
 
     /** {@hide} */
+    public static File getExpandDirectory() {
+        return DIR_ANDROID_EXPAND;
+    }
+
+    /** {@hide} */
     public static File getDataSystemDirectory() {
         return new File(getDataDirectory(), "system");
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1b79497..dd73e53 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -605,6 +605,30 @@
      */
     public static File buildUniqueFile(File parent, String mimeType, String displayName)
             throws FileNotFoundException {
+        final String[] parts = splitFileName(mimeType, displayName);
+        final String name = parts[0];
+        final String ext = parts[1];
+        File file = buildFile(parent, name, ext);
+
+        // If conflicting file, try adding counter suffix
+        int n = 0;
+        while (file.exists()) {
+            if (n++ >= 32) {
+                throw new FileNotFoundException("Failed to create unique file");
+            }
+            file = buildFile(parent, name + " (" + n + ")", ext);
+        }
+
+        return file;
+    }
+
+    /**
+     * Splits file name into base name and extension.
+     * If the display name doesn't have an extension that matches the requested MIME type, the
+     * extension is regarded as a part of filename and default extension for that MIME type is
+     * appended.
+     */
+    public static String[] splitFileName(String mimeType, String displayName) {
         String name;
         String ext;
 
@@ -642,18 +666,11 @@
             }
         }
 
-        File file = buildFile(parent, name, ext);
-
-        // If conflicting file, try adding counter suffix
-        int n = 0;
-        while (file.exists()) {
-            if (n++ >= 32) {
-                throw new FileNotFoundException("Failed to create unique file");
-            }
-            file = buildFile(parent, name + " (" + n + ")", ext);
+        if (ext == null) {
+            ext = "";
         }
 
-        return file;
+        return new String[] { name, ext };
     }
 
     private static File buildFile(File parent, String name, String ext) {
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index dd10df3..1d464c0 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -50,6 +50,7 @@
     boolean isLightDeviceIdleMode();
 
     void reboot(boolean confirm, String reason, boolean wait);
+    void rebootSafeMode(boolean confirm, boolean wait);
     void shutdown(boolean confirm, String reason, boolean wait);
     void crash(String message);
 
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 5872f74..b947c97 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -18,7 +18,9 @@
 
 import android.annotation.Nullable;
 import android.util.ArrayMap;
+
 import com.android.internal.util.XmlUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -26,9 +28,11 @@
 import java.io.IOException;
 
 /**
- * A mapping from String values to various types that can be saved to persistent and later
- * restored.
+ * A mapping from String keys to values of various types. The set of types
+ * supported by this class is purposefully restricted to simple objects that can
+ * safely be persisted to and restored from disk.
  *
+ * @see Bundle
  */
 public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
         XmlUtils.WriteMapCallback {
@@ -57,6 +61,7 @@
      */
     public PersistableBundle() {
         super();
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -67,6 +72,7 @@
      */
     public PersistableBundle(int capacity) {
         super(capacity);
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -77,6 +83,7 @@
      */
     public PersistableBundle(PersistableBundle b) {
         super(b);
+        mFlags = b.mFlags;
     }
 
 
@@ -101,6 +108,7 @@
      */
     private PersistableBundle(ArrayMap<String, Object> map) {
         super();
+        mFlags = FLAG_DEFUSABLE;
 
         // First stuff everything in.
         putAll(map);
@@ -123,6 +131,7 @@
 
     /* package */ PersistableBundle(Parcel parcelledData, int length) {
         super(parcelledData, length);
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -278,5 +287,4 @@
         }
         return "PersistableBundle[" + mMap.toString() + "]";
     }
-
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2a4507c..8bc903b 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -318,6 +318,13 @@
     public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
 
     /**
+     * User activity event type: Accessibility taking action on behalf of user.
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3;
+
+    /**
      * User activity flag: If already dimmed, extend the dim timeout
      * but do not brighten.  This flag is useful for keeping the screen on
      * a little longer without causing a visible change such as when
@@ -419,6 +426,12 @@
     public static final String REBOOT_REQUESTED_BY_DEVICE_OWNER = "deviceowner";
 
     /**
+     * The 'reason' value used when rebooting in safe mode
+     * @hide
+     */
+    public static final String REBOOT_SAFE_MODE = "safemode";
+
+    /**
      * The value to pass as the 'reason' argument to android_reboot().
      * @hide
      */
@@ -896,6 +909,21 @@
     }
 
     /**
+     * Reboot the device. Will not return if the reboot is successful.
+     * <p>
+     * Requires the {@link android.Manifest.permission#REBOOT} permission.
+     * </p>
+     * @hide
+     */
+    public void rebootSafeMode() {
+        try {
+            mService.rebootSafeMode(false, true);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns true if the device is currently in power save mode.  When in this mode,
      * applications should reduce their functionality in order to conserve battery as
      * much as possible.  You can monitor for changes to this state with
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index e2675b1..0ff0154 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.os;
 
 import android.Manifest;
@@ -882,25 +883,13 @@
         }
     }
 
-    /**
-     * Return whether the calling user is running in a "locked" state. A user is
-     * unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndLocked() {
         return isUserRunningAndLocked(Process.myUserHandle());
     }
 
-    /**
-     * Return whether the given user is running in a "locked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     *
-     * @param user to retrieve the unlocked state for.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndLocked(UserHandle user) {
         try {
@@ -911,25 +900,13 @@
         }
     }
 
-    /**
-     * Return whether the calling user is running in an "unlocked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndUnlocked() {
         return isUserRunningAndUnlocked(Process.myUserHandle());
     }
 
-    /**
-     * Return whether the given user is running in an "unlocked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
-     *
-     * @param user to retrieve the unlocked state for.
-     */
+    /** @removed */
     @Deprecated
     public boolean isUserRunningAndUnlocked(UserHandle user) {
         try {
@@ -941,22 +918,37 @@
     }
 
     /**
-     * Return whether the calling user is running in an "unlocked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
+     * Return whether the calling user is running in an "unlocked" state.
+     * <p>
+     * On devices with direct boot, a user is unlocked only after they've
+     * entered their credentials (such as a lock pattern or PIN). On devices
+     * without direct boot, a user is unlocked as soon as it starts.
+     * <p>
+     * When a user is locked, only device-protected data storage is available.
+     * When a user is unlocked, both device-protected and credential-protected
+     * private app data storage is available.
+     *
+     * @see Intent#ACTION_USER_UNLOCKED
+     * @see Context#createDeviceProtectedStorageContext()
      */
     public boolean isUserUnlocked() {
         return isUserUnlocked(Process.myUserHandle());
     }
 
     /**
-     * Return whether the given user is running in an "unlocked" state. A user
-     * is unlocked only after they've entered their credentials (such as a lock
-     * pattern or PIN), and credential-encrypted private app data storage is
-     * available.
+     * Return whether the given user is running in an "unlocked" state.
+     * <p>
+     * On devices with direct boot, a user is unlocked only after they've
+     * entered their credentials (such as a lock pattern or PIN). On devices
+     * without direct boot, a user is unlocked as soon as it starts.
+     * <p>
+     * When a user is locked, only device-protected data storage is available.
+     * When a user is unlocked, both device-protected and credential-protected
+     * private app data storage is available.
      *
      * @param user to retrieve the unlocked state for.
+     * @see Intent#ACTION_USER_UNLOCKED
+     * @see Context#createDeviceProtectedStorageContext()
      */
     public boolean isUserUnlocked(UserHandle user) {
         return isUserUnlocked(user.getIdentifier());
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 61e6b95..22aec63 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -35,6 +35,7 @@
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
@@ -1025,6 +1026,20 @@
         }
     }
 
+    /**
+     * Return if data stored at the given path will be encrypted while at rest.
+     * This can help apps avoid the overhead of double-encrypting data.
+     */
+    public boolean isEncrypted(File file) {
+        if (FileUtils.contains(Environment.getDataDirectory(), file)) {
+            return isEncrypted();
+        } else if (FileUtils.contains(Environment.getExpandDirectory(), file)) {
+            return true;
+        }
+        // TODO: extend to support shared storage
+        return false;
+    }
+
     /** {@hide}
      * Is this device encryptable or already encrypted?
      * @return true for encryptable or encrypted
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index ebb12fd..47dc6c3 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -113,8 +113,8 @@
     private int mSharedPreferencesMode;
 
     private static final int STORAGE_DEFAULT = 0;
-    private static final int STORAGE_DEVICE_ENCRYPTED = 1;
-    private static final int STORAGE_CREDENTIAL_ENCRYPTED = 2;
+    private static final int STORAGE_DEVICE_PROTECTED = 1;
+    private static final int STORAGE_CREDENTIAL_PROTECTED = 2;
 
     private int mStorage = STORAGE_DEFAULT;
 
@@ -360,35 +360,57 @@
 
     /**
      * Explicitly set the storage location used internally by this class to be
-     * device-encrypted storage.
+     * device-protected storage.
      * <p>
-     * Data stored in device-encrypted storage is typically encrypted with a key
-     * tied to the physical device, and it can be accessed when the device has
-     * booted successfully, both <em>before and after</em> the user has
-     * authenticated with their credentials (such as a lock pattern or PIN).
-     * Because device-encrypted data is available before user authentication,
-     * you should carefully consider what data you store using this mode.
+     * On devices with direct boot, data stored in this location is encrypted
+     * with a key tied to the physical device, and it can be accessed
+     * immediately after the device has booted successfully, both
+     * <em>before and after</em> the user has authenticated with their
+     * credentials (such as a lock pattern or PIN).
+     * <p>
+     * Because device-protected data is available without user authentication,
+     * you should carefully limit the data you store using this Context. For
+     * example, storing sensitive authentication tokens or passwords in the
+     * device-protected area is strongly discouraged.
      *
-     * @see Context#createDeviceEncryptedStorageContext()
+     * @see Context#createDeviceProtectedStorageContext()
      */
-    public void setStorageDeviceEncrypted() {
-        mStorage = STORAGE_DEVICE_ENCRYPTED;
+    public void setStorageDeviceProtected() {
+        mStorage = STORAGE_DEVICE_PROTECTED;
         mSharedPreferences = null;
     }
 
+    /** @removed */
+    @Deprecated
+    public void setStorageDeviceEncrypted() {
+        setStorageDeviceProtected();
+    }
+
     /**
      * Explicitly set the storage location used internally by this class to be
-     * credential-encrypted storage.
+     * credential-protected storage. This is the default storage area for apps
+     * unless {@code forceDeviceProtectedStorage} was requested.
+     * <p>
+     * On devices with direct boot, data stored in this location is encrypted
+     * with a key tied to user credentials, which can be accessed
+     * <em>only after</em> the user has entered their credentials (such as a
+     * lock pattern or PIN).
      *
-     * @see Context#createCredentialEncryptedStorageContext()
+     * @see Context#createCredentialProtectedStorageContext()
      * @hide
      */
     @SystemApi
-    public void setStorageCredentialEncrypted() {
-        mStorage = STORAGE_CREDENTIAL_ENCRYPTED;
+    public void setStorageCredentialProtected() {
+        mStorage = STORAGE_CREDENTIAL_PROTECTED;
         mSharedPreferences = null;
     }
 
+    /** @removed */
+    @Deprecated
+    public void setStorageCredentialEncrypted() {
+        setStorageCredentialProtected();
+    }
+
     /**
      * Gets a SharedPreferences instance that preferences managed by this will
      * use.
@@ -400,11 +422,11 @@
         if (mSharedPreferences == null) {
             final Context storageContext;
             switch (mStorage) {
-                case STORAGE_DEVICE_ENCRYPTED:
-                    storageContext = mContext.createDeviceEncryptedStorageContext();
+                case STORAGE_DEVICE_PROTECTED:
+                    storageContext = mContext.createDeviceProtectedStorageContext();
                     break;
-                case STORAGE_CREDENTIAL_ENCRYPTED:
-                    storageContext = mContext.createCredentialEncryptedStorageContext();
+                case STORAGE_CREDENTIAL_PROTECTED:
+                    storageContext = mContext.createCredentialProtectedStorageContext();
                     break;
                 default:
                     storageContext = mContext;
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 2445bc2..1ec00db 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -38,6 +38,8 @@
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
+import com.android.internal.annotations.GuardedBy;
+
 /**
  * Turns a {@link SeekBar} into a volume control.
  * @hide
@@ -67,6 +69,10 @@
     private Observer mVolumeObserver;
     private int mOriginalStreamVolume;
     private int mLastAudibleStreamVolume;
+    // When the old handler is destroyed and a new one is created, there could be a situation where
+    // this is accessed at the same time in different handlers. So, access to this field needs to be
+    // synchronized.
+    @GuardedBy("this")
     private Ringtone mRingtone;
     private int mLastProgress = -1;
     private boolean mMuted;
@@ -174,9 +180,11 @@
     }
 
     private void onInitSample() {
-        mRingtone = RingtoneManager.getRingtone(mContext, mDefaultUri);
-        if (mRingtone != null) {
-            mRingtone.setStreamType(mStreamType);
+        synchronized (this) {
+            mRingtone = RingtoneManager.getRingtone(mContext, mDefaultUri);
+            if (mRingtone != null) {
+                mRingtone.setStreamType(mStreamType);
+            }
         }
     }
 
@@ -192,16 +200,19 @@
             if (mCallback != null) {
                 mCallback.onSampleStarting(this);
             }
-            if (mRingtone != null) {
-                try {
-                    mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
-                            .getAudioAttributes())
-                            .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
-                                    AudioAttributes.FLAG_BYPASS_MUTE)
-                            .build());
-                    mRingtone.play();
-                } catch (Throwable e) {
-                    Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
+
+            synchronized (this) {
+                if (mRingtone != null) {
+                    try {
+                        mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
+                                .getAudioAttributes())
+                                .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
+                                        AudioAttributes.FLAG_BYPASS_MUTE)
+                                .build());
+                        mRingtone.play();
+                    } catch (Throwable e) {
+                        Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
+                    }
                 }
             }
         }
@@ -216,8 +227,10 @@
     }
 
     private void onStopSample() {
-        if (mRingtone != null) {
-            mRingtone.stop();
+        synchronized (this) {
+            if (mRingtone != null) {
+                mRingtone.stop();
+            }
         }
     }
 
@@ -274,7 +287,9 @@
     }
 
     public boolean isSamplePlaying() {
-        return mRingtone != null && mRingtone.isPlaying();
+        synchronized (this) {
+            return mRingtone != null && mRingtone.isPlaying();
+        }
     }
 
     public void startSample() {
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index def303a..b06d503 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -44,7 +44,8 @@
  * Only the system, the default SMS application, and the default phone app
  * (See {@link android.telecom.TelecomManager#getDefaultDialerPackage()}), and carrier apps
  * (See {@link android.service.carrier.CarrierService}) can read, and write to the blockednumber
- * provider.
+ * provider. However, {@link #canCurrentUserBlockNumbers(Context)} can be accessed by any
+ * application.
  * </p>
  *
  * <h3> Data </h3>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 136abab..5fc2899 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2093,7 +2093,7 @@
          */
         public static void clearConfiguration(Configuration inoutConfig) {
             inoutConfig.fontScale = 0;
-            if (!inoutConfig.userSetLocale) {
+            if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) {
                 inoutConfig.setLocales(LocaleList.getEmptyLocaleList());
             }
         }
@@ -2708,24 +2708,6 @@
         public static final String VOLUME_MASTER = "volume_master";
 
         /**
-         * Master volume mute (int 1 = mute, 0 = not muted).
-         *
-         * @hide
-         */
-        public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
-
-        private static final Validator VOLUME_MASTER_MUTE_VALIDATOR = sBooleanValidator;
-
-        /**
-         * Microphone mute (int 1 = mute, 0 = not muted).
-         *
-         * @hide
-         */
-        public static final String MICROPHONE_MUTE = "microphone_mute";
-
-        private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator;
-
-        /**
          * Master mono (int 1 = mono, 0 = normal).
          *
          * @hide
@@ -3515,8 +3497,6 @@
             PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
             PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
             PRIVATE_SETTINGS.add(VOLUME_MASTER);
-            PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE);
-            PRIVATE_SETTINGS.add(MICROPHONE_MUTE);
             PRIVATE_SETTINGS.add(MASTER_MONO);
             PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME);
             PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT);
@@ -3594,8 +3574,6 @@
             VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR);
             VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR);
             VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR);
-            VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR);
-            VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR);
             VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR);
             VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR);
             VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR);
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index 1d90505..5434e2e 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -34,4 +34,5 @@
     void startUnlockAndRun(in Tile tile);
 
     void onDialogHidden(in Tile tile);
+    void onStartSuccessful(in Tile tile);
 }
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 85f1955..3d7d53e 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -37,8 +37,6 @@
     private static final String TAG = "Tile";
 
     /**
-     * This is the default state of any tile, until updated by the {@link TileService}.
-     * <p>
      * An unavailable state indicates that for some reason this tile is not currently
      * available to the user for some reason, and will have no click action.  The tile's
      * icon will be tinted differently to reflect this state.
@@ -57,7 +55,7 @@
 
     /**
      * This represents a tile that is currently active. (e.g. wifi is connected, bluetooth is on,
-     * cast is casting).
+     * cast is casting).  This is the default state.
      */
     public static final int STATE_ACTIVE = 2;
 
diff --git a/core/java/android/speech/tts/AudioPlaybackQueueItem.java b/core/java/android/speech/tts/AudioPlaybackQueueItem.java
index d4fea53..ed7534d 100644
--- a/core/java/android/speech/tts/AudioPlaybackQueueItem.java
+++ b/core/java/android/speech/tts/AudioPlaybackQueueItem.java
@@ -16,7 +16,7 @@
 package android.speech.tts;
 
 import android.content.Context;
-import android.media.AudioSystem;
+import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.ConditionVariable;
@@ -57,7 +57,7 @@
         int sessionId = mAudioParams.mSessionId;
         mPlayer = MediaPlayer.create(
                 mContext, mUri, null, mAudioParams.mAudioAttributes,
-                sessionId > 0 ? sessionId : AudioSystem.AUDIO_SESSION_ALLOCATE);
+                sessionId > 0 ? sessionId : AudioManager.AUDIO_SESSION_ID_GENERATE);
         if (mPlayer == null) {
             dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT);
             return;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index fc075de..1eaa7cf 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -19,7 +19,7 @@
 import android.app.Service;
 import android.content.Intent;
 import android.media.AudioAttributes;
-import android.media.AudioSystem;
+import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -659,7 +659,7 @@
         /**
          * Audio session identifier. May be used to associate audio playback with one of the
          * {@link android.media.audiofx.AudioEffect} objects. If not specified by client,
-         * it should be equal to {@link AudioSystem#AUDIO_SESSION_ALLOCATE}.
+         * it should be equal to {@link AudioManager#AUDIO_SESSION_ID_GENERATE}.
          */
         public final int mSessionId;
 
@@ -684,7 +684,7 @@
 
         /** Create AudioOutputParams with default values */
         AudioOutputParams() {
-            mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+            mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
             mVolume = Engine.DEFAULT_VOLUME;
             mPan = Engine.DEFAULT_PAN;
             mAudioAttributes = null;
@@ -722,7 +722,7 @@
             return new AudioOutputParams(
                     paramsBundle.getInt(
                             Engine.KEY_PARAM_SESSION_ID,
-                            AudioSystem.AUDIO_SESSION_ALLOCATE),
+                            AudioManager.AUDIO_SESSION_ID_GENERATE),
                     paramsBundle.getFloat(
                             Engine.KEY_PARAM_VOLUME,
                             Engine.DEFAULT_VOLUME),
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index bfe5c3f..a1bc2d1 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -247,23 +247,22 @@
      */
     public static Metrics isBoring(CharSequence text, TextPaint paint,
             TextDirectionHeuristic textDir, Metrics metrics) {
-        char[] temp = TextUtils.obtain(500);
-        int length = text.length();
+        final int MAX_BUF_LEN = 500;
+        final char[] buffer = TextUtils.obtain(MAX_BUF_LEN);
+        final int textLength = text.length();
         boolean boring = true;
 
         outer:
-        for (int i = 0; i < length; i += 500) {
-            int j = i + 500;
+        for (int start = 0; start < textLength; start += MAX_BUF_LEN) {
+            final int end = Math.min(start + MAX_BUF_LEN, textLength);
 
-            if (j > length)
-                j = length;
+            // No need to worry about getting half codepoints, since we reject surrogate code units
+            // as non-boring as soon we see one.
+            TextUtils.getChars(text, start, end, buffer, 0);
 
-            TextUtils.getChars(text, i, j, temp, 0);
-
-            int n = j - i;
-
-            for (int a = 0; a < n; a++) {
-                char c = temp[a];
+            final int len = end - start;
+            for (int i = 0; i < len; i++) {
+                final char c = buffer[i];
 
                 if (c == '\n' || c == '\t' ||
                         (c >= 0x0590 && c <= 0x08FF) ||  // RTL scripts
@@ -279,17 +278,19 @@
                 }
             }
 
-            if (textDir != null && textDir.isRtl(temp, 0, n)) {
+            // TODO: This looks a little suspicious, and in some cases can result in O(n^2)
+            // run time. Consider moving outside the loop.
+            if (textDir != null && textDir.isRtl(buffer, 0, len)) {
                boring = false;
                break outer;
             }
         }
 
-        TextUtils.recycle(temp);
+        TextUtils.recycle(buffer);
 
         if (boring && text instanceof Spanned) {
             Spanned sp = (Spanned) text;
-            Object[] styles = sp.getSpans(0, length, ParagraphStyle.class);
+            Object[] styles = sp.getSpans(0, textLength, ParagraphStyle.class);
             if (styles.length > 0) {
                 boring = false;
             }
@@ -302,7 +303,7 @@
             }
 
             TextLine line = TextLine.obtain();
-            line.set(paint, text, 0, length, Layout.DIR_LEFT_TO_RIGHT,
+            line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
                     Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null);
             fm.width = (int) Math.ceil(line.metrics(fm));
             TextLine.recycle(line);
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index 93a156b..e9153dd 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -1013,7 +1013,7 @@
          * @return This instance.
          */
         public MeasureBuilder setIntegerPart(long integerPart) {
-            return setNumber(String.valueOf(integerPart));
+            return setIntegerPart(String.valueOf(integerPart));
         }
 
         /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 55393b1..e5ab971 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10210,44 +10210,38 @@
      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
      *
-     * @param changedView the view that changed, either <code>this</code> or an ancestor
-     * @param visibility aggregated visibility of this view's parent or changedView, whichever
-     *                   is closer
-     * @return the aggregated visibility for this view
+     * @param isVisible true if this view's visibility to the user is uninterrupted by its
+     *                  ancestors or by window visibility
+     * @return true if this view is visible to the user, not counting clipping or overlapping
      */
-    int dispatchVisibilityAggregated(View changedView, @Visibility int visibility) {
-        visibility = Math.max(visibility, getVisibility());
-        onVisibilityAggregated(changedView, visibility);
-        return visibility;
+    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
+        final boolean thisVisible = getVisibility() == VISIBLE;
+        if (thisVisible) {
+            onVisibilityAggregated(isVisible);
+        }
+        return thisVisible && isVisible;
     }
 
     /**
      * Called when the user-visibility of this View is potentially affected by a change
      * to this view itself, an ancestor view or the window this view is attached to.
      *
-     * <p>The visibility value reported will be one of {@link #VISIBLE}, {@link #INVISIBLE}
-     * or {@link #GONE}, reflecting this view's aggregated visibility within its window.
-     * The visibility parameter takes this view's own visibility into account.
-     * Calls to this method may be repeated with the same visibility values; implementations
-     * should ensure that work done is not duplicated unnecessarily.</p>
-     *
-     * @param changedView the view that changed; may be <code>this</code> or an ancestor
-     * @param visibility the visibility of this view in the context of the full window
+     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
+     *                  and this view's window is also visible
      */
     @CallSuper
-    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
-        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
-        if (visible && mAttachInfo != null) {
+    public void onVisibilityAggregated(boolean isVisible) {
+        if (isVisible && mAttachInfo != null) {
             initialAwakenScrollBars();
         }
 
         final Drawable dr = mBackground;
-        if (dr != null && visible != dr.isVisible()) {
-            dr.setVisible(visible, false);
+        if (dr != null && isVisible != dr.isVisible()) {
+            dr.setVisible(isVisible, false);
         }
         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
-        if (fg != null && visible != fg.isVisible()) {
-            fg.setVisible(visible, false);
+        if (fg != null && isVisible != fg.isVisible()) {
+            fg.setVisible(isVisible, false);
         }
     }
 
@@ -11376,7 +11370,7 @@
                 // to change animation states.
                 if (mParent != null && getWindowVisibility() == VISIBLE &&
                         ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
-                    dispatchVisibilityAggregated(this, newVisibility);
+                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
                 }
                 notifySubtreeAccessibilityStateChangedIfNeeded();
             }
@@ -15289,7 +15283,9 @@
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
             if (isShown()) {
-                onVisibilityAggregated(this, vis);
+                // Calling onVisibilityChanged directly here since the subtree will also
+                // receive dispatchAttachedToWindow and this same call
+                onVisibilityAggregated(vis == VISIBLE);
             }
         }
 
@@ -15312,7 +15308,9 @@
             if (vis != GONE) {
                 onWindowVisibilityChanged(GONE);
                 if (isShown()) {
-                    onVisibilityAggregated(this, GONE);
+                    // Invoking onVisibilityAggregated directly here since the subtree
+                    // will also receive detached from window
+                    onVisibilityAggregated(false);
                 }
             }
         }
@@ -18001,12 +17999,14 @@
 
         /*
          * Regardless of whether we're setting a new background or not, we want
-         * to clear the previous drawable.
+         * to clear the previous drawable. setVisible first while we still have the callback set.
          */
         if (mBackground != null) {
+            if (isAttachedToWindow()) {
+                mBackground.setVisible(false, false);
+            }
             mBackground.setCallback(null);
             unscheduleDrawable(mBackground);
-            mBackground.setVisible(false, false);
         }
 
         if (background != null) {
@@ -18043,12 +18043,19 @@
                 requestLayout = true;
             }
 
+            // Set mBackground before we set this as the callback and start making other
+            // background drawable state change calls. In particular, the setVisible call below
+            // can result in drawables attempting to start animations or otherwise invalidate,
+            // which requires the view set as the callback (us) to recognize the drawable as
+            // belonging to it as per verifyDrawable.
+            mBackground = background;
             background.setCallback(this);
             if (background.isStateful()) {
                 background.setState(getDrawableState());
             }
-            background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
-            mBackground = background;
+            if (isAttachedToWindow()) {
+                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            }
 
             applyBackgroundTint();
 
@@ -18084,6 +18091,7 @@
 
         mBackgroundSizeChanged = true;
         invalidate(true);
+        invalidateOutline();
     }
 
     /**
@@ -18227,9 +18235,11 @@
         }
 
         if (mForegroundInfo.mDrawable != null) {
+            if (isAttachedToWindow()) {
+                mForegroundInfo.mDrawable.setVisible(false, false);
+            }
             mForegroundInfo.mDrawable.setCallback(null);
             unscheduleDrawable(mForegroundInfo.mDrawable);
-            mForegroundInfo.mDrawable.setVisible(false, false);
         }
 
         mForegroundInfo.mDrawable = foreground;
@@ -18244,7 +18254,9 @@
                 foreground.setState(getDrawableState());
             }
             applyForegroundTint();
-            foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            if (isAttachedToWindow()) {
+                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            }
         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
             mPrivateFlags |= PFLAG_SKIP_DRAW;
         }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 36a5db1..816d9c4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1291,20 +1291,19 @@
     }
 
     @Override
-    int dispatchVisibilityAggregated(View changedView, @Visibility int visibility) {
-        visibility = super.dispatchVisibilityAggregated(changedView, visibility);
+    boolean dispatchVisibilityAggregated(boolean isVisible) {
+        isVisible = super.dispatchVisibilityAggregated(isVisible);
         final int count = mChildrenCount;
         final View[] children = mChildren;
         for (int i = 0; i < count; i++) {
-            // Only dispatch to children with at least the same level of visibility
-            // that we're reporting, otherwise it won't affect that child/subtree at all
-            // so it's not worth telling them about it. Note that we use <= here
-            // because VISIBLE < INVISIBLE < GONE as constant values.
-            if (children[i].getVisibility() <= visibility) {
-                children[i].dispatchVisibilityAggregated(changedView, visibility);
+            // Only dispatch to visible children. Not visible children and their subtrees already
+            // know that they aren't visible and that's not going to change as a result of
+            // whatever triggered this dispatch.
+            if (children[i].getVisibility() == VISIBLE) {
+                children[i].dispatchVisibilityAggregated(isVisible);
             }
         }
-        return visibility;
+        return isVisible;
     }
 
     @Override
@@ -4995,6 +4994,8 @@
         if (child.hasFocus()) {
             requestChildFocus(child, child.findFocus());
         }
+        dispatchVisibilityAggregated(isAttachedToWindow() && getWindowVisibility() == VISIBLE
+                && isShown());
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fecf892..a2295ce 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1472,7 +1472,7 @@
         if (viewVisibilityChanged) {
             mAttachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
-            host.dispatchVisibilityAggregated(host, viewVisibility);
+            host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                 endDragResizing();
                 destroyHardwareResources();
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9f05990..63f3744 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -566,8 +566,8 @@
          * @param data The data list to populate with shortcuts.
          * @param menu The current menu, which may be null.
          */
-        public void onProvideKeyboardShortcuts(
-                List<KeyboardShortcutGroup> data, @Nullable Menu menu);
+        default public void onProvideKeyboardShortcuts(
+                List<KeyboardShortcutGroup> data, @Nullable Menu menu) { };
     }
 
     /** @hide */
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index a1cbc1d..887cc3a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -170,7 +170,7 @@
                     sWindowManagerService = getWindowManagerService();
                     ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return sWindowManagerService;
@@ -192,7 +192,7 @@
                             },
                             imm.getClient(), imm.getInputContext());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to open window session", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return sWindowSession;
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index df33698..35d3bf9 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -50,7 +50,10 @@
     private static final String TAG = SpellCheckerSubtype.class.getSimpleName();
     private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
     private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
-    private static final int SUBTYPE_ID_NONE = 0;
+    /**
+     * @hide
+     */
+    public static final int SUBTYPE_ID_NONE = 0;
     private static final String SUBTYPE_LANGUAGE_TAG_NONE = "";
 
     private final int mSubtypeId;
diff --git a/core/java/android/webkit/IWebViewUpdateService.aidl b/core/java/android/webkit/IWebViewUpdateService.aidl
index 5697dfc..9434f0c 100644
--- a/core/java/android/webkit/IWebViewUpdateService.aidl
+++ b/core/java/android/webkit/IWebViewUpdateService.aidl
@@ -54,6 +54,11 @@
     WebViewProviderInfo[] getValidWebViewPackages();
 
     /**
+     * Fetch all packages that could potentially implement WebView.
+     */
+    WebViewProviderInfo[] getAllWebViewPackages();
+
+    /**
      * Used by DevelopmentSetting to get the name of the WebView provider currently in use.
      */
     String getCurrentWebViewPackageName();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2eb258f..b16508e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -32,6 +32,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.StrictMode;
@@ -2622,6 +2623,16 @@
         mProvider.getViewDelegate().onFinishTemporaryDetach();
     }
 
+    @Override
+    public Handler getHandler() {
+        return mProvider.getViewDelegate().getHandler(super.getHandler());
+    }
+
+    @Override
+    public View findFocus() {
+        return mProvider.getViewDelegate().findFocus(super.findFocus());
+    }
+
     /**
      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
      *
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 3d72260..f1bf890 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -103,8 +103,10 @@
     public static final int LIBLOAD_FAILED_JNI_CALL = 7;
 
     // more error codes for waiting for WebView preparation
-    public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8;
-    public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9;
+    public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 8;
+
+    // error for namespace lookup
+    public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10;
 
     private static String getWebViewPreparationErrorReason(int error) {
         switch (error) {
@@ -112,8 +114,6 @@
                 return "Time out waiting for Relro files being created";
             case LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES:
                 return "No WebView installed";
-            case LIBLOAD_WEBVIEW_BEING_REPLACED:
-                return "Time out waiting for WebView to be replaced";
             case LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN:
                 return "Crashed for unknown reason";
         }
@@ -128,98 +128,9 @@
         public MissingWebViewPackageException(Exception e) { super(e); }
     }
 
-    private static String TAG_START = "webviewproviders";
-    private static String TAG_WEBVIEW_PROVIDER = "webviewprovider";
-    private static String TAG_PACKAGE_NAME = "packageName";
-    private static String TAG_DESCRIPTION = "description";
-    // Whether or not the provider must be explicitly chosen by the user to be used.
-    private static String TAG_AVAILABILITY = "availableByDefault";
-    private static String TAG_SIGNATURE = "signature";
-    private static String TAG_FALLBACK = "isFallback";
-
-    /**
-     * Reads all signatures at the current depth (within the current provider) from the XML parser.
-     */
-    private static String[] readSignatures(XmlResourceParser parser) throws IOException,
-            XmlPullParserException {
-        List<String> signatures = new ArrayList<String>();
-        int outerDepth = parser.getDepth();
-        while(XmlUtils.nextElementWithin(parser, outerDepth)) {
-            if (parser.getName().equals(TAG_SIGNATURE)) {
-                // Parse the value within the signature tag
-                String signature = parser.nextText();
-                signatures.add(signature);
-            } else {
-                Log.e(LOGTAG, "Found an element in a webview provider that is not a signature");
-            }
-        }
-        return signatures.toArray(new String[signatures.size()]);
-    }
-
-    /**
-     * Returns all packages declared in the framework resources as potential WebView providers.
-     * @hide
-     * */
-    public static WebViewProviderInfo[] getWebViewPackages() {
-        int numFallbackPackages = 0;
-        XmlResourceParser parser = null;
-        List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
-        try {
-            parser = AppGlobals.getInitialApplication().getResources().getXml(
-                    com.android.internal.R.xml.config_webview_packages);
-            XmlUtils.beginDocument(parser, TAG_START);
-            while(true) {
-                XmlUtils.nextElement(parser);
-                String element = parser.getName();
-                if (element == null) {
-                    break;
-                }
-                if (element.equals(TAG_WEBVIEW_PROVIDER)) {
-                    String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME);
-                    if (packageName == null) {
-                        throw new MissingWebViewPackageException(
-                                "WebView provider in framework resources missing package name");
-                    }
-                    String description = parser.getAttributeValue(null, TAG_DESCRIPTION);
-                    if (description == null) {
-                        throw new MissingWebViewPackageException(
-                                "WebView provider in framework resources missing description");
-                    }
-                    boolean availableByDefault = "true".equals(
-                            parser.getAttributeValue(null, TAG_AVAILABILITY));
-                    boolean isFallback = "true".equals(
-                            parser.getAttributeValue(null, TAG_FALLBACK));
-                    WebViewProviderInfo currentProvider =
-                            new WebViewProviderInfo(packageName, description, availableByDefault,
-                                isFallback, readSignatures(parser));
-                    if (currentProvider.isFallbackPackage()) {
-                        numFallbackPackages++;
-                        if (numFallbackPackages > 1) {
-                            throw new AndroidRuntimeException(
-                                    "There can be at most one webview fallback package.");
-                        }
-                    }
-                    webViewProviders.add(currentProvider);
-                }
-                else {
-                    Log.e(LOGTAG, "Found an element that is not a webview provider");
-                }
-            }
-        } catch(XmlPullParserException e) {
-            throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
-        } catch(IOException e) {
-            throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
-        } finally {
-            if (parser != null) parser.close();
-        }
-        return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
-    }
-
-
     // TODO (gsennton) remove when committing webview xts test change
     public static String getWebViewPackageName() {
-        WebViewProviderInfo[] providers = getWebViewPackages();
-        return providers[0].packageName;
+        return null;
     }
 
     /**
@@ -239,7 +150,8 @@
      * Load the native library for the given package name iff that package
      * name is the same as the one providing the webview.
      */
-    public static int loadWebViewNativeLibraryFromPackage(String packageName) {
+    public static int loadWebViewNativeLibraryFromPackage(String packageName,
+                                                          ClassLoader clazzLoader) {
         int ret = waitForProviderAndSetPackageInfo();
         if (ret != LIBLOAD_SUCCESS) {
             return ret;
@@ -247,7 +159,7 @@
         if (!sPackageInfo.packageName.equals(packageName))
             return LIBLOAD_WRONG_PACKAGE_NAME;
 
-        return loadNativeLibrary();
+        return loadNativeLibrary(clazzLoader);
     }
 
     static WebViewFactoryProvider getProvider() {
@@ -333,15 +245,16 @@
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
             }
 
-            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
-            loadNativeLibrary();
-            Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
-
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
             try {
                 initialApplication.getAssets().addAssetPathAsSharedLibrary(
                         webViewContext.getApplicationInfo().sourceDir);
                 ClassLoader clazzLoader = webViewContext.getClassLoader();
+
+                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
+                loadNativeLibrary(clazzLoader);
+                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                 try {
                     return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
@@ -633,7 +546,7 @@
     }
 
     // Assumes that we have waited for relro creation and set sPackageInfo
-    private static int loadNativeLibrary() {
+    private static int loadNativeLibrary(ClassLoader clazzLoader) {
         if (!sAddressSpaceReserved) {
             Log.e(LOGTAG, "can't load with relro file; address space not reserved");
             return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
@@ -641,9 +554,10 @@
 
         String[] args = getWebViewNativeLibraryPaths(sPackageInfo);
         int result = nativeLoadWithRelroFile(args[0] /* path32 */,
-                                                 args[1] /* path64 */,
-                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
-                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
+                                             args[1] /* path64 */,
+                                             CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
+                                             CHROMIUM_WEBVIEW_NATIVE_RELRO_64,
+                                             clazzLoader);
         if (result != LIBLOAD_SUCCESS) {
             Log.w(LOGTAG, "failed to load with relro file, proceeding without");
         } else if (DEBUG) {
@@ -672,5 +586,6 @@
     private static native boolean nativeCreateRelroFile(String lib32, String lib64,
                                                         String relro32, String relro64);
     private static native int nativeLoadWithRelroFile(String lib32, String lib64,
-                                                          String relro32, String relro64);
+                                                      String relro32, String relro64,
+                                                      ClassLoader clazzLoader);
 }
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 94d231c..e5b65e7 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -28,6 +28,7 @@
 import android.net.http.SslCertificate;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.Message;
 import android.print.PrintDocumentAdapter;
 import android.view.DragEvent;
@@ -386,6 +387,10 @@
         public void onFinishTemporaryDetach();
 
         public void onActivityResult(int requestCode, int resultCode, Intent data);
+
+        public Handler getHandler(Handler originalHandler);
+
+        public View findFocus(View originalFocusedView);
     }
 
     interface ScrollDelegate {
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index 64c2caa..75ccf35 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -150,6 +150,8 @@
     private WebViewProviderInfo(Parcel in) {
         packageName = in.readString();
         description = in.readString();
+        availableByDefault = (in.readInt() > 0);
+        isFallback = (in.readInt() > 0);
         signatures = in.createStringArray();
         packageInfo = null;
     }
@@ -163,6 +165,8 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(packageName);
         out.writeString(description);
+        out.writeInt(availableByDefault ? 1 : 0);
+        out.writeInt(isFallback ? 1 : 0);
         out.writeStringArray(signatures);
     }
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 4bcb406..942cbcb 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1827,7 +1827,7 @@
             return;
         }
 
-        Layout layout = getActiveLayout();
+        Layout layout = mTextView.getLayout();
         final int offset = mTextView.getSelectionStart();
         final int line = layout.getLineForOffset(offset);
         final int top = layout.getLineTop(line);
@@ -2192,27 +2192,35 @@
             mCursorDrawable[cursorIndex] = mTextView.getContext().getDrawable(
                     mTextView.mCursorDrawableRes);
         final Drawable drawable = mCursorDrawable[cursorIndex];
-        final int left = clampCursorHorizontalPosition(drawable, horizontal);
+        final int left = clampHorizontalPosition(drawable, horizontal);
         final int width = drawable.getIntrinsicWidth();
         drawable.setBounds(left, top - mTempRect.top, left + width,
                 bottom + mTempRect.bottom);
     }
 
     /**
-     * Return clamped position for the cursor. If the cursor is within the boundaries of the view,
-     * then it is offset with the left padding of the cursor drawable. If the cursor is at
+     * Return clamped position for the drawable. If the drawable is within the boundaries of the
+     * view, then it is offset with the left padding of the cursor drawable. If the drawable is at
      * the beginning or the end of the text then its drawable edge is aligned with left or right of
-     * the view boundary.
+     * the view boundary. If the drawable is null, horizontal parameter is aligned to left or right
+     * of the view.
      *
-     * @param drawable   Cursor drawable.
-     * @param horizontal Horizontal position for the cursor.
-     * @return The clamped horizontal position for the cursor.
+     * @param drawable Drawable. Can be null.
+     * @param horizontal Horizontal position for the drawable.
+     * @return The clamped horizontal position for the drawable.
      */
-    private final int clampCursorHorizontalPosition(final Drawable drawable, float
-            horizontal) {
+    private int clampHorizontalPosition(@Nullable final Drawable drawable, float horizontal) {
         horizontal = Math.max(0.5f, horizontal - 0.5f);
         if (mTempRect == null) mTempRect = new Rect();
-        drawable.getPadding(mTempRect);
+
+        int drawableWidth = 0;
+        if (drawable != null) {
+            drawable.getPadding(mTempRect);
+            drawableWidth = drawable.getIntrinsicWidth();
+        } else {
+            mTempRect.setEmpty();
+        }
+
         int scrollX = mTextView.getScrollX();
         float horizontalDiff = horizontal - scrollX;
         int viewClippedWidth = mTextView.getWidth() - mTextView.getCompoundPaddingLeft()
@@ -2221,9 +2229,11 @@
         final int left;
         if (horizontalDiff >= (viewClippedWidth - 1f)) {
             // at the rightmost position
-            final int cursorWidth = drawable.getIntrinsicWidth();
-            left = viewClippedWidth + scrollX - (cursorWidth - mTempRect.right);
-        } else if (Math.abs(horizontalDiff) <= 1f) {
+            left = viewClippedWidth + scrollX - (drawableWidth - mTempRect.right);
+        } else if (Math.abs(horizontalDiff) <= 1f ||
+                (TextUtils.isEmpty(mTextView.getText())
+                        && (TextView.VERY_WIDE - scrollX) <= (viewClippedWidth + 1f)
+                        && horizontal <= 1f)) {
             // at the leftmost position
             left = scrollX - mTempRect.left;
         } else {
@@ -3772,10 +3782,10 @@
                                 + mHandleHeight);
             } else {
                 // We have a single cursor.
-                Layout layout = getActiveLayout();
+                Layout layout = mTextView.getLayout();
                 int line = layout.getLineForOffset(mTextView.getSelectionStart());
-                float primaryHorizontal =
-                        layout.getPrimaryHorizontal(mTextView.getSelectionStart());
+                float primaryHorizontal = clampHorizontalPosition(null,
+                        layout.getPrimaryHorizontal(mTextView.getSelectionStart()));
                 mSelectionBounds.set(
                         primaryHorizontal,
                         layout.getLineTop(line),
@@ -4152,7 +4162,7 @@
                 prepareCursorControllers();
                 return;
             }
-            layout = getActiveLayout();
+            layout = mTextView.getLayout();
 
             boolean offsetChanged = offset != mPreviousOffset;
             if (offsetChanged || parentScrolled) {
@@ -4322,19 +4332,6 @@
         public void onDetached() {}
     }
 
-    /**
-     * Returns the active layout (hint or text layout). Note that the text layout can be null.
-     */
-    private Layout getActiveLayout() {
-        Layout layout = mTextView.getLayout();
-        Layout hintLayout = mTextView.getHintLayout();
-        if (TextUtils.isEmpty(layout.getText()) && hintLayout != null &&
-                !TextUtils.isEmpty(hintLayout.getText())) {
-            layout = hintLayout;
-        }
-        return layout;
-    }
-
     private class InsertionHandleView extends HandleView {
         private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000;
         private static final int RECENT_CUT_COPY_DURATION = 15 * 1000; // seconds
@@ -4431,7 +4428,7 @@
             final Drawable drawable = mCursorCount > 0 ? mCursorDrawable[0] : null;
             if (drawable != null) {
                 final float horizontal = layout.getPrimaryHorizontal(offset);
-                return clampCursorHorizontalPosition(drawable, horizontal) + mTempRect.left;
+                return clampHorizontalPosition(drawable, horizontal) + mTempRect.left;
             }
             return super.getCursorHorizontalPosition(layout, offset);
         }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 1321221..6d7313d 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1644,7 +1644,7 @@
         boolean handled = false;
         int action = event.getAction();
         if (KeyEvent.isConfirmKey(keyCode)
-                && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) {
+                && event.hasNoModifiers() && action != KeyEvent.ACTION_UP) {
             handled = resurrectSelectionIfNeeded();
             if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) {
                 keyPressed();
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 71b5ce9..222a040 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -913,7 +913,9 @@
         if (mDrawable != null) {
             mDrawable.setCallback(null);
             unscheduleDrawable(mDrawable);
-            mDrawable.setVisible(false, false);
+            if (isAttachedToWindow()) {
+                mDrawable.setVisible(false, false);
+            }
         }
 
         mDrawable = d;
@@ -924,8 +926,9 @@
             if (d.isStateful()) {
                 d.setState(getDrawableState());
             }
-            d.setVisible(isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(),
-                    true);
+            if (isAttachedToWindow()) {
+                d.setVisible(getWindowVisibility() == VISIBLE && isShown(), true);
+            }
             d.setLevel(mLevel);
             mDrawableWidth = d.getIntrinsicWidth();
             mDrawableHeight = d.getIntrinsicHeight();
@@ -1501,10 +1504,10 @@
     }
 
     @Override
-    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
-        super.onVisibilityAggregated(changedView, visibility);
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
         if (mDrawable != null) {
-            mDrawable.setVisible(visibility == VISIBLE, false);
+            mDrawable.setVisible(isVisible, false);
         }
     }
 
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index e0ef86c..9e8f778 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -869,10 +869,10 @@
         // Either expand children with weight to take up available space or
         // shrink them if they extend beyond our current bounds. If we skipped
         // measurement on any children, we need to measure them now.
-        final int delta = heightSize - mTotalLength
+        int remainingExcess = heightSize - mTotalLength
                 + (mAllowInconsistentMeasurement ? 0 : consumedExcessSpace);
-        if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
-            final float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
+        if (skippedMeasure || remainingExcess != 0 && totalWeight > 0.0f) {
+            float remainingWeightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             mTotalLength = 0;
 
@@ -883,9 +883,12 @@
                 }
 
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                final float childExtra = lp.weight;
-                if (childExtra > 0) {
-                    final int share = (int) (childExtra * delta / weightSum);
+                final float childWeight = lp.weight;
+                if (childWeight > 0) {
+                    final int share = (int) (childWeight * remainingExcess / remainingWeightSum);
+                    remainingExcess -= share;
+                    remainingWeightSum -= childWeight;
+
                     final int childHeight;
                     if (lp.height == 0 && (!mAllowInconsistentMeasurement
                             || heightMode == MeasureSpec.EXACTLY)) {
@@ -1244,10 +1247,10 @@
         // Either expand children with weight to take up available space or
         // shrink them if they extend beyond our current bounds. If we skipped
         // measurement on any children, we need to measure them now.
-        final int delta = widthSize - mTotalLength
+        int remainingExcess = widthSize - mTotalLength
                 + (mAllowInconsistentMeasurement ? 0 : usedExcessSpace);
-        if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
-            final float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
+        if (skippedMeasure || remainingExcess != 0 && totalWeight > 0.0f) {
+            float remainingWeightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
             maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
@@ -1262,9 +1265,12 @@
                 }
 
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                final float childExtra = lp.weight;
-                if (childExtra > 0) {
-                    final int share = (int) (childExtra * delta / weightSum);
+                final float childWeight = lp.weight;
+                if (childWeight > 0) {
+                    final int share = (int) (childWeight * remainingExcess / remainingWeightSum);
+                    remainingExcess -= share;
+                    remainingWeightSum -= childWeight;
+
                     final int childWidth;
                     if (lp.width == 0 && (!mAllowInconsistentMeasurement
                             || widthMode == MeasureSpec.EXACTLY)) {
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index dcadb6a..36e0c77 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -879,12 +879,13 @@
     /**
      * Filter key down events. By forwarding key down events to this function,
      * views using non-modal ListPopupWindow can have it handle key selection of items.
-     *  
+     *
      * @param keyCode keyCode param passed to the host view's onKeyDown
      * @param event event param passed to the host view's onKeyDown
      * @return true if the event was handled, false if it was ignored.
-     * 
+     *
      * @see #setModal(boolean)
+     * @see #onKeyUp(int, KeyEvent)
      */
     public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
         // when the drop down is shown, we drive it directly
@@ -972,14 +973,15 @@
     }
 
     /**
-     * Filter key down events. By forwarding key up events to this function,
+     * Filter key up events. By forwarding key up events to this function,
      * views using non-modal ListPopupWindow can have it handle key selection of items.
-     *  
+     *
      * @param keyCode keyCode param passed to the host view's onKeyUp
      * @param event event param passed to the host view's onKeyUp
      * @return true if the event was handled, false if it was ignored.
-     * 
+     *
      * @see #setModal(boolean)
+     * @see #onKeyDown(int, KeyEvent)
      */
     public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
         if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
@@ -998,11 +1000,11 @@
      * Filter pre-IME key events. By forwarding {@link View#onKeyPreIme(int, KeyEvent)}
      * events to this function, views using ListPopupWindow can have it dismiss the popup
      * when the back key is pressed.
-     *  
+     *
      * @param keyCode keyCode param passed to the host view's onKeyPreIme
      * @param event event param passed to the host view's onKeyPreIme
      * @return true if the event was handled, false if it was ignored.
-     * 
+     *
      * @see #setModal(boolean)
      */
     public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index dd6a41f..a1417f0 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -16,12 +16,10 @@
 
 package android.widget;
 
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
-
 import com.android.internal.R;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
@@ -54,10 +52,46 @@
 
 import java.lang.ref.WeakReference;
 
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
+
 /**
- * <p>A popup window that can be used to display an arbitrary view. The popup
- * window is a floating container that appears on top of the current
- * activity.</p>
+ * <p>
+ * This class represents a popup window that can be used to display an
+ * arbitrary view. The popup window is a floating container that appears on top
+ * of the current activity.
+ * </p>
+ * <a name="Animation"></a>
+ * <h3>Animation</h3>
+ * <p>
+ * On all versions of Android, popup window enter and exit animations may be
+ * specified by calling {@link #setAnimationStyle(int)} and passing the
+ * resource ID for an animation style that defines {@code windowEnterAnimation}
+ * and {@code windowExitAnimation}. For example, passing
+ * {@link android.R.style#Animation_Dialog} will give a scale and alpha
+ * animation.
+ * </br>
+ * A window animation style may also be specified in the popup window's style
+ * XML via the {@link android.R.styleable#PopupWindow_popupAnimationStyle popupAnimationStyle}
+ * attribute.
+ * </p>
+ * <p>
+ * Starting with API 23, more complex popup window enter and exit transitions
+ * may be specified by calling either {@link #setEnterTransition(Transition)}
+ * or {@link #setExitTransition(Transition)} and passing a  {@link Transition}.
+ * </br>
+ * Popup enter and exit transitions may also be specified in the popup window's
+ * style XML via the {@link android.R.styleable#PopupWindow_popupEnterTransition popupEnterTransition}
+ * and {@link android.R.styleable#PopupWindow_popupExitTransition popupExitTransition}
+ * attributes, respectively.
+ * </p>
+ *
+ * @attr ref android.R.styleable#PopupWindow_overlapAnchor
+ * @attr ref android.R.styleable#PopupWindow_popupAnimationStyle
+ * @attr ref android.R.styleable#PopupWindow_popupBackground
+ * @attr ref android.R.styleable#PopupWindow_popupElevation
+ * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
+ * @attr ref android.R.styleable#PopupWindow_popupExitTransition
  *
  * @see android.widget.AutoCompleteTextView
  * @see android.widget.Spinner
@@ -351,15 +385,54 @@
         setFocusable(focusable);
     }
 
-    public void setEnterTransition(Transition enterTransition) {
+    /**
+     * Sets the enter transition to be used when the popup window is shown.
+     *
+     * @param enterTransition the enter transition, or {@code null} to clear
+     * @see #getEnterTransition()
+     * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
+     */
+    public void setEnterTransition(@Nullable Transition enterTransition) {
         mEnterTransition = enterTransition;
     }
 
-    public void setExitTransition(Transition exitTransition) {
+    /**
+     * Returns the enter transition to be used when the popup window is shown.
+     *
+     * @return the enter transition, or {@code null} if not set
+     * @see #setEnterTransition(Transition)
+     * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
+     */
+    @Nullable
+    public Transition getEnterTransition() {
+        return mEnterTransition;
+    }
+
+    /**
+     * Sets the exit transition to be used when the popup window is dismissed.
+     *
+     * @param exitTransition the exit transition, or {@code null} to clear
+     * @see #getExitTransition()
+     * @attr ref android.R.styleable#PopupWindow_popupExitTransition
+     */
+    public void setExitTransition(@Nullable Transition exitTransition) {
         mExitTransition = exitTransition;
     }
 
     /**
+     * Returns the exit transition to be used when the popup window is
+     * dismissed.
+     *
+     * @return the exit transition, or {@code null} if not set
+     * @see #setExitTransition(Transition)
+     * @attr ref android.R.styleable#PopupWindow_popupExitTransition
+     */
+    @Nullable
+    public Transition getExitTransition() {
+        return mExitTransition;
+    }
+
+    /**
      * Sets the bounds used as the epicenter of the enter and exit transitions.
      * <p>
      * Transitions use a point or Rect, referred to as the epicenter, to orient
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index dd0f91e..e9fa26c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -617,6 +617,7 @@
     private void swapCurrentDrawable(Drawable newDrawable) {
         final Drawable oldDrawable = mCurrentDrawable;
         mCurrentDrawable = newDrawable;
+
         if (oldDrawable != mCurrentDrawable) {
             if (oldDrawable != null) {
                 oldDrawable.setVisible(false, false);
@@ -1645,10 +1646,9 @@
     }
 
     @Override
-    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
-        super.onVisibilityAggregated(changedView, visibility);
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
 
-        final boolean isVisible = visibility == VISIBLE;
         if (isVisible != mAggregatedIsVisible) {
             mAggregatedIsVisible = isVisible;
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fbedbda..3195097 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -285,8 +285,8 @@
 
     private static final RectF TEMP_RECTF = new RectF();
 
-    // XXX should be much larger
-    private static final int VERY_WIDE = 1024*1024;
+    /** @hide */
+    static final int VERY_WIDE = 1024 * 1024; // XXX should be much larger
     private static final int ANIMATED_SCROLL_GAP = 250;
 
     private static final InputFilter[] NO_FILTERS = new InputFilter[0];
@@ -6552,7 +6552,7 @@
                 if (TextUtils.equals(content.subSequence(start, end), text.text)) {
                     if (text.text instanceof Spanned) {
                         // OK to copy spans only.
-                        TextUtils.copySpansFrom((Spanned) text.text, start, end,
+                        TextUtils.copySpansFrom((Spanned) text.text, 0, end - start,
                                 Object.class, content, start);
                     }
                 } else {
@@ -9646,7 +9646,10 @@
     }
 
     boolean canShare() {
-        return canCopy() && isDeviceProvisioned();
+        if (!getContext().canStartActivityForResult() || !isDeviceProvisioned()) {
+            return false;
+        }
+        return canCopy();
     }
 
     boolean isDeviceProvisioned() {
@@ -9669,16 +9672,10 @@
     }
 
     boolean canProcessText() {
-        if (!getContext().canStartActivityForResult() || getId() == View.NO_ID
-                || hasPasswordTransformationMethod()) {
+        if (getId() == View.NO_ID) {
             return false;
         }
-
-        if (mText.length() > 0 && hasSelection() && mEditor != null) {
-            return true;
-        }
-
-        return false;
+        return canShare();
     }
 
     boolean canSelectAllText() {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 9897b12..80e1db0 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -128,8 +128,8 @@
                 com.android.internal.R.string.whichSendApplication,
                 com.android.internal.R.string.whichSendApplicationNamed),
         SENDTO(Intent.ACTION_SENDTO,
-                com.android.internal.R.string.whichSendApplication,
-                com.android.internal.R.string.whichSendApplicationNamed),
+                com.android.internal.R.string.whichSendToApplication,
+                com.android.internal.R.string.whichSendToApplicationNamed),
         SEND_MULTIPLE(Intent.ACTION_SEND_MULTIPLE,
                 com.android.internal.R.string.whichSendApplication,
                 com.android.internal.R.string.whichSendApplicationNamed),
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 90ee05e..f3ae688 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -854,7 +854,8 @@
         private final HashMap<String, String> mCopyOnWriteDataStore = new HashMap<>();
 
         private boolean mCopyOnWrite = false;
-        private String mEnabledInputMethodsStrCache;
+        @NonNull
+        private String mEnabledInputMethodsStrCache = "";
         @UserIdInt
         private int mCurrentUserId;
         private int[] mCurrentProfileIds = new int[0];
@@ -908,14 +909,6 @@
             return imsList;
         }
 
-        @Deprecated
-        public InputMethodSettings(
-                Resources res, ContentResolver resolver,
-                HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
-                @UserIdInt int userId) {
-            this(res, resolver, methodMap, methodList, userId, false /* copyOnWrite */);
-        }
-
         public InputMethodSettings(
                 Resources res, ContentResolver resolver,
                 HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
@@ -949,7 +942,7 @@
             // TODO: mCurrentProfileIds should be updated here.
         }
 
-        private void putString(final String key, final String str) {
+        private void putString(@NonNull final String key, @Nullable final String str) {
             if (mCopyOnWrite) {
                 mCopyOnWriteDataStore.put(key, str);
             } else {
@@ -957,12 +950,15 @@
             }
         }
 
-        private String getString(final String key) {
+        @Nullable
+        private String getString(@NonNull final String key, @Nullable final String defaultValue) {
+            final String result;
             if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
-                final String result = mCopyOnWriteDataStore.get(key);
-                return result != null ? result : "";
+                result = mCopyOnWriteDataStore.get(key);
+            } else {
+                result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
             }
-            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+            return result != null ? result : defaultValue;
         }
 
         private void putInt(final String key, final int value) {
@@ -1124,16 +1120,24 @@
             return res;
         }
 
-        private void putEnabledInputMethodsStr(String str) {
+        private void putEnabledInputMethodsStr(@Nullable String str) {
             if (DEBUG) {
                 Slog.d(TAG, "putEnabledInputMethodStr: " + str);
             }
-            putString(Settings.Secure.ENABLED_INPUT_METHODS, str);
-            mEnabledInputMethodsStrCache = str;
+            if (TextUtils.isEmpty(str)) {
+                // OK to coalesce to null, since getEnabledInputMethodsStr() can take care of the
+                // empty data scenario.
+                putString(Settings.Secure.ENABLED_INPUT_METHODS, null);
+            } else {
+                putString(Settings.Secure.ENABLED_INPUT_METHODS, str);
+            }
+            // TODO: Update callers of putEnabledInputMethodsStr to make str @NonNull.
+            mEnabledInputMethodsStrCache = (str != null ? str : "");
         }
 
+        @NonNull
         public String getEnabledInputMethodsStr() {
-            mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS);
+            mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS, "");
             if (DEBUG) {
                 Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache
                         + ", " + mCurrentUserId);
@@ -1187,11 +1191,17 @@
             saveSubtypeHistory(subtypeHistory, imeId, subtypeId);
         }
 
-        private void putSubtypeHistoryStr(String str) {
+        private void putSubtypeHistoryStr(@NonNull String str) {
             if (DEBUG) {
                 Slog.d(TAG, "putSubtypeHistoryStr: " + str);
             }
-            putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            if (TextUtils.isEmpty(str)) {
+                // OK to coalesce to null, since getSubtypeHistoryStr() can take care of the empty
+                // data scenario.
+                putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, null);
+            } else {
+                putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            }
         }
 
         public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
@@ -1308,8 +1318,9 @@
             return imsList;
         }
 
+        @NonNull
         private String getSubtypeHistoryStr() {
-            final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY);
+            final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, "");
             if (DEBUG) {
                 Slog.d(TAG, "getSubtypeHistoryStr: " + history);
             }
@@ -1332,8 +1343,9 @@
             putInt(Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId);
         }
 
+        @Nullable
         public String getSelectedInputMethod() {
-            final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD);
+            final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD, null);
             if (DEBUG) {
                 Slog.d(TAG, "getSelectedInputMethodStr: " + imi);
             }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8de9c09..d11787d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -107,7 +107,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 141 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 142 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 919254a..66cc975 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -149,6 +149,12 @@
     native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
 
+    /**
+     * Zygote unmount storage space on initializing.
+     * This method is called once.
+     */
+    native protected static void nativeUnmountStorageOnInit();
+
     private static void callPostForkChildHooks(int debugFlags, boolean isSystemServer,
             String instructionSet) {
         VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 3abea26..b658f87 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -643,6 +643,9 @@
             // Zygote.
             Trace.setTracingEnabled(false);
 
+            // Zygote process unmounts root storage spaces.
+            Zygote.nativeUnmountStorageOnInit();
+
             if (startSystemServer) {
                 startSystemServer(abiList, socketName);
             }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index df48d6d..fbd8fb5 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2073,11 +2073,7 @@
     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list) {
         final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
         if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) {
-            try {
-                mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
-            } catch (AbstractMethodError e) {
-                // We run into this if the app is using supportlib.
-            }
+            mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index ce03bb8..8682030 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -308,9 +308,6 @@
         private static final int MIN_OVERFLOW_SIZE = 2;
         private static final int MAX_OVERFLOW_SIZE = 4;
 
-        /* The duration of the overflow button vector animation duration. */
-        private static final int OVERFLOW_BUTTON_ANIMATION_DELAY = 400;
-
         private final Context mContext;
         private final View mParent;  // Parent for the popup window.
         private final PopupWindow mPopupWindow;
@@ -377,18 +374,6 @@
             }
         };
 
-        /* Runnable to reset the overflow button's drawable after an overflow transition. */
-        private final Runnable mResetOverflowButtonDrawable = new Runnable() {
-            @Override
-            public void run() {
-                if (mIsOverflowOpen) {
-                    mOverflowButton.setImageDrawable(mArrow);
-                } else {
-                    mOverflowButton.setImageDrawable(mOverflow);
-                }
-            }
-        };
-
         private boolean mDismissed = true; // tracks whether this popup is dismissed or dismissing.
         private boolean mHidden; // tracks whether this popup is hidden or hiding.
 
@@ -902,7 +887,9 @@
                 final Size containerSize = mOverflowPanelSize;
                 setSize(mContentContainer, containerSize);
                 mMainPanel.setAlpha(0);
+                mMainPanel.setVisibility(View.INVISIBLE);
                 mOverflowPanel.setAlpha(1);
+                mOverflowPanel.setVisibility(View.VISIBLE);
                 mOverflowButton.setImageDrawable(mArrow);
 
                 // Update x-coordinates depending on RTL state.
@@ -941,7 +928,9 @@
                 final Size containerSize = mMainPanelSize;
                 setSize(mContentContainer, containerSize);
                 mMainPanel.setAlpha(1);
+                mMainPanel.setVisibility(View.VISIBLE);
                 mOverflowPanel.setAlpha(0);
+                mOverflowPanel.setVisibility(View.INVISIBLE);
                 mOverflowButton.setImageDrawable(mOverflow);
 
                 if (hasOverflow()) {
@@ -1327,8 +1316,6 @@
                         mToArrow.start();
                         openOverflow();
                     }
-                    overflowButton.postDelayed(
-                            mResetOverflowButtonDrawable, OVERFLOW_BUTTON_ANIMATION_DELAY);
                 }
             });
             return overflowButton;
@@ -1389,6 +1376,10 @@
                     // Disable the overflow button while it's animating.
                     // It will be re-enabled when the animation stops.
                     mOverflowButton.setEnabled(false);
+                    // Ensure both panels have visibility turned on when the overflow animation
+                    // starts.
+                    mMainPanel.setVisibility(View.VISIBLE);
+                    mOverflowPanel.setVisibility(View.VISIBLE);
                 }
 
                 @Override
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8ef1a22..c6db0ed 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -36,7 +36,7 @@
     android_app_Activity.cpp \
     android_app_ApplicationLoaders.cpp \
     android_app_NativeActivity.cpp \
-    android_auditing_SecurityLog.cpp \
+    android_app_admin_SecurityLog.cpp \
     android_opengl_EGL14.cpp \
     android_opengl_EGLExt.cpp \
     android_opengl_GLES10.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 95323f7..7ff38fd5 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -109,7 +109,7 @@
  * JNI-based registration functions.  Note these are properly contained in
  * namespace android.
  */
-extern int register_android_auditing_SecurityLog(JNIEnv* env);
+extern int register_android_app_admin_SecurityLog(JNIEnv* env);
 extern int register_android_content_AssetManager(JNIEnv* env);
 extern int register_android_util_EventLog(JNIEnv* env);
 extern int register_android_util_Log(JNIEnv* env);
@@ -1253,7 +1253,7 @@
     REG_JNI(register_android_util_EventLog),
     REG_JNI(register_android_util_Log),
     REG_JNI(register_android_util_PathParser),
-    REG_JNI(register_android_auditing_SecurityLog),
+    REG_JNI(register_android_app_admin_SecurityLog),
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index fb9b1e5..4001283 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -73,6 +73,9 @@
         case SkEncodedFormat::kWBMP_SkEncodedFormat:
             mimeType = "image/vnd.wap.wbmp";
             break;
+        case SkEncodedFormat::kRAW_SkEncodedFormat:
+            mimeType = "image/x-adobe-dng";
+            break;
         default:
             mimeType = nullptr;
             break;
diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp
new file mode 100644
index 0000000..da47c4c
--- /dev/null
+++ b/core/jni/android_app_admin_SecurityLog.cpp
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+
+#include <fcntl.h>
+
+#include "JNIHelp.h"
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "log/logger.h"
+
+// The size of the tag number comes out of the payload size.
+#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
+
+namespace android {
+
+static jclass gCollectionClass;
+static jmethodID gCollectionAddID;
+
+static jclass gEventClass;
+static jmethodID gEventInitID;
+
+static jclass gIntegerClass;
+static jfieldID gIntegerValueID;
+
+static jclass gLongClass;
+static jfieldID gLongValueID;
+
+static jclass gFloatClass;
+static jfieldID gFloatValueID;
+
+static jclass gStringClass;
+
+
+static jboolean android_app_admin_SecurityLog_isLoggingEnabled(JNIEnv* env,
+                                                    jobject /* clazz */) {
+    return (bool)__android_log_security();
+}
+
+static jint android_app_admin_SecurityLog_writeEvent_String(JNIEnv* env,
+                                                    jobject /* clazz */,
+                                                    jint tag, jstring value) {
+    uint8_t buf[MAX_EVENT_PAYLOAD];
+
+    // Don't throw NPE -- I feel like it's sort of mean for a logging function
+    // to be all crashy if you pass in NULL -- but make the NULL value explicit.
+    const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
+    uint32_t len = strlen(str);
+    size_t max = sizeof(buf) - sizeof(len) - 2;  // Type byte, final newline
+    if (len > max) len = max;
+
+    buf[0] = EVENT_TYPE_STRING;
+    memcpy(&buf[1], &len, sizeof(len));
+    memcpy(&buf[1 + sizeof(len)], str, len);
+    buf[1 + sizeof(len) + len] = '\n';
+
+    if (value != NULL) env->ReleaseStringUTFChars(value, str);
+    return __android_log_security_bwrite(tag, buf, 2 + sizeof(len) + len);
+}
+
+static jint android_app_admin_SecurityLog_writeEvent_Array(JNIEnv* env, jobject clazz,
+                                                   jint tag, jobjectArray value) {
+    if (value == NULL) {
+        return android_app_admin_SecurityLog_writeEvent_String(env, clazz, tag, NULL);
+    }
+
+    uint8_t buf[MAX_EVENT_PAYLOAD];
+    const size_t max = sizeof(buf) - 1;  // leave room for final newline
+    size_t pos = 2;  // Save room for type tag & array count
+
+    jsize copied = 0, num = env->GetArrayLength(value);
+    for (; copied < num && copied < 255; ++copied) {
+        jobject item = env->GetObjectArrayElement(value, copied);
+        if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
+            if (pos + 1 + sizeof(jint) > max) break;
+            const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
+            jint len = strlen(str);
+            if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
+            buf[pos++] = EVENT_TYPE_STRING;
+            memcpy(&buf[pos], &len, sizeof(len));
+            memcpy(&buf[pos + sizeof(len)], str, len);
+            pos += sizeof(len) + len;
+            if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
+        } else if (env->IsInstanceOf(item, gIntegerClass)) {
+            jint intVal = env->GetIntField(item, gIntegerValueID);
+            if (pos + 1 + sizeof(intVal) > max) break;
+            buf[pos++] = EVENT_TYPE_INT;
+            memcpy(&buf[pos], &intVal, sizeof(intVal));
+            pos += sizeof(intVal);
+        } else if (env->IsInstanceOf(item, gLongClass)) {
+            jlong longVal = env->GetLongField(item, gLongValueID);
+            if (pos + 1 + sizeof(longVal) > max) break;
+            buf[pos++] = EVENT_TYPE_LONG;
+            memcpy(&buf[pos], &longVal, sizeof(longVal));
+            pos += sizeof(longVal);
+        } else if (env->IsInstanceOf(item, gFloatClass)) {
+            jfloat floatVal = env->GetFloatField(item, gFloatValueID);
+            if (pos + 1 + sizeof(floatVal) > max) break;
+            buf[pos++] = EVENT_TYPE_FLOAT;
+            memcpy(&buf[pos], &floatVal, sizeof(floatVal));
+            pos += sizeof(floatVal);
+        } else {
+            jniThrowException(env,
+                    "java/lang/IllegalArgumentException",
+                    "Invalid payload item type");
+            return -1;
+        }
+        env->DeleteLocalRef(item);
+    }
+
+    buf[0] = EVENT_TYPE_LIST;
+    buf[1] = copied;
+    buf[pos++] = '\n';
+    return __android_log_security_bwrite(tag, buf, pos);
+}
+
+static void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) {
+    struct logger_list *logger_list;
+    if (startTime) {
+        logger_list = android_logger_list_alloc_time(loggerMode,
+                log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
+    } else {
+        logger_list = android_logger_list_alloc(loggerMode, 0, 0);
+    }
+    if (!logger_list) {
+        jniThrowIOException(env, errno);
+        return;
+    }
+
+    if (!android_logger_open(logger_list, LOG_ID_SECURITY)) {
+        jniThrowIOException(env, errno);
+        android_logger_list_free(logger_list);
+        return;
+    }
+
+    while (1) {
+        log_msg log_msg;
+        int ret = android_logger_list_read(logger_list, &log_msg);
+
+        if (ret == 0) {
+            break;
+        }
+        if (ret < 0) {
+            if (ret == -EINTR) {
+                continue;
+            }
+            if (ret == -EINVAL) {
+                jniThrowException(env, "java/io/IOException", "Event too short");
+            } else if (ret != -EAGAIN) {
+                jniThrowIOException(env, -ret);  // Will throw on return
+            }
+            break;
+        }
+
+        if (log_msg.id() != LOG_ID_SECURITY) {
+            continue;
+        }
+
+        jsize len = ret;
+        jbyteArray array = env->NewByteArray(len);
+        if (array == NULL) {
+            break;
+        }
+
+        jbyte *bytes = env->GetByteArrayElements(array, NULL);
+        memcpy(bytes, log_msg.buf, len);
+        env->ReleaseByteArrayElements(array, bytes, 0);
+
+        jobject event = env->NewObject(gEventClass, gEventInitID, array);
+        if (event == NULL) {
+            break;
+        }
+
+        env->CallBooleanMethod(out, gCollectionAddID, event);
+        env->DeleteLocalRef(event);
+        env->DeleteLocalRef(array);
+    }
+
+    android_logger_list_close(logger_list);
+}
+
+static void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* clazz */,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out);
+}
+
+static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */,
+                                             jlong timestamp,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out);
+}
+
+static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out);
+}
+
+static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */,
+                                             jlong timestamp,
+                                             jobject out) {
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out);
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gRegisterMethods[] = {
+    /* name, signature, funcPtr */
+    { "isLoggingEnabled",
+      "()Z",
+      (void*) android_app_admin_SecurityLog_isLoggingEnabled
+    },
+    { "writeEvent",
+      "(ILjava/lang/String;)I",
+      (void*) android_app_admin_SecurityLog_writeEvent_String
+    },
+    { "writeEvent",
+      "(I[Ljava/lang/Object;)I",
+      (void*) android_app_admin_SecurityLog_writeEvent_Array
+    },
+    { "readEvents",
+      "(Ljava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEvents
+    },
+    { "readEventsSince",
+      "(JLjava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEventsSince
+    },
+    { "readPreviousEvents",
+      "(Ljava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readPreviousEvents
+    },
+    { "readEventsOnWrapping",
+      "(JLjava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEventsOnWrapping
+    },
+};
+
+static struct { const char *name; jclass *clazz; } gClasses[] = {
+    { "android/app/admin/SecurityLog$SecurityEvent", &gEventClass },
+    { "java/lang/Integer", &gIntegerClass },
+    { "java/lang/Long", &gLongClass },
+    { "java/lang/Float", &gFloatClass },
+    { "java/lang/String", &gStringClass },
+    { "java/util/Collection", &gCollectionClass },
+};
+
+static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
+    { &gIntegerClass, "value", "I", &gIntegerValueID },
+    { &gLongClass, "value", "J", &gLongValueID },
+    { &gFloatClass, "value", "F", &gFloatValueID },
+};
+
+static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
+    { &gEventClass, "<init>", "([B)V", &gEventInitID },
+    { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
+};
+
+int register_android_app_admin_SecurityLog(JNIEnv* env) {
+    for (int i = 0; i < NELEM(gClasses); ++i) {
+        jclass clazz = FindClassOrDie(env, gClasses[i].name);
+        *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
+    }
+
+    for (int i = 0; i < NELEM(gFields); ++i) {
+        *gFields[i].id = GetFieldIDOrDie(env,
+                *gFields[i].c, gFields[i].name, gFields[i].ft);
+    }
+
+    for (int i = 0; i < NELEM(gMethods); ++i) {
+        *gMethods[i].id = GetMethodIDOrDie(env,
+                *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
+    }
+
+    return RegisterMethodsOrDie(
+            env,
+            "android/app/admin/SecurityLog",
+            gRegisterMethods, NELEM(gRegisterMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 7314fbc..e17de17 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -78,11 +78,11 @@
 static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
         jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha,
         jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
-        jint strokeLineCap, jint strokeLineJoin) {
+        jint strokeLineCap, jint strokeLineJoin, jint fillType) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
     fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha,
             trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap,
-            strokeLineJoin);
+            strokeLineJoin, fillType);
 }
 
 static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
@@ -331,7 +331,7 @@
         {"nDraw", "(JJJLandroid/graphics/Rect;ZZ)V", (void*)draw},
         {"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
         {"nCreateFullPath", "!(J)J", (void*)createFullPath},
-        {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+        {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
         {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
         {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
         {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 3e4e352..1bc4285 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -200,7 +200,7 @@
         ALOGE("Error creating AudioRecord: Error retrieving session id pointer");
         return (jint) AUDIO_JAVA_ERROR;
     }
-    int sessionId = nSession[0];
+    audio_session_t sessionId = (audio_session_t) nSession[0];
     env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
     nSession = NULL;
 
@@ -385,7 +385,7 @@
     }
 
     return nativeToJavaStatus(
-            lpRecorder->start((AudioSystem::sync_event_t)event, triggerSession));
+            lpRecorder->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
 }
 
 
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 1eb0111..7496124 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -109,7 +109,8 @@
     jfieldID    mRule;
     jfieldID    mFormat;
     jfieldID    mRouteFlags;
-    jfieldID    mRegistrationId;
+    jfieldID    mDeviceType;
+    jfieldID    mDeviceAddress;
     jfieldID    mMixType;
     jfieldID    mCallbackFlags;
 } gAudioMixFields;
@@ -388,7 +389,7 @@
 }
 
 static void
-android_media_AudioSystem_recording_callback(int event, int session, int source,
+android_media_AudioSystem_recording_callback(int event, audio_session_t session, int source,
         const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
         audio_patch_handle_t patchHandle)
 {
@@ -1539,7 +1540,7 @@
 static jint
 android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
 {
-    return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
+    return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
 }
 
 static void
@@ -1561,13 +1562,15 @@
 {
     nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
     nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
+    nAudioMix->mDeviceType = (audio_devices_t)
+            env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
 
-    jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
-                                                           gAudioMixFields.mRegistrationId);
-    const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
-    nAudioMix->mRegistrationId = String8(nRegistrationId);
-    env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
-    env->DeleteLocalRef(jRegistrationId);
+    jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
+                                                           gAudioMixFields.mDeviceAddress);
+    const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
+    nAudioMix->mDeviceAddress = String8(nDeviceAddress);
+    env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
+    env->DeleteLocalRef(jDeviceAddress);
 
     nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
 
@@ -1857,7 +1860,8 @@
     gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
                                                 "Landroid/media/AudioFormat;");
     gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
-    gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
+    gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
+    gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
                                                       "Ljava/lang/String;");
     gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
     gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 302cf63..024c21d 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -235,7 +235,7 @@
         ALOGE("Error creating AudioTrack: Error retrieving session id pointer");
         return (jint) AUDIO_JAVA_ERROR;
     }
-    int sessionId = nSession[0];
+    audio_session_t sessionId = (audio_session_t) nSession[0];
     env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
     nSession = NULL;
 
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index a9003c1..a7ac5b8 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -28,6 +28,7 @@
 #include <DamageAccumulator.h>
 #include <Matrix.h>
 #include <RenderNode.h>
+#include <renderthread/CanvasContext.h>
 #include <TreeInfo.h>
 #include <Paint.h>
 
@@ -487,15 +488,7 @@
 
         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
             if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
-            ATRACE_NAME("Update SurfaceView position");
 
-            JNIEnv* env = jnienv();
-            jobject localref = env->NewLocalRef(mWeakRef);
-            if (CC_UNLIKELY(!localref)) {
-                jnienv()->DeleteWeakGlobalRef(mWeakRef);
-                mWeakRef = nullptr;
-                return;
-            }
             Matrix4 transform;
             info.damageAccumulator->computeCurrentTransform(&transform);
             const RenderProperties& props = node.properties();
@@ -505,10 +498,13 @@
             bounds.right -= info.windowInsetLeft;
             bounds.top -= info.windowInsetTop;
             bounds.bottom -= info.windowInsetTop;
-            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
-                    (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
-                    (jint) bounds.right, (jint) bounds.bottom);
-            env->DeleteLocalRef(localref);
+
+            auto functor = std::bind(
+                std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this,
+                (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top,
+                (jint) bounds.right, (jint) bounds.bottom);
+
+            info.canvasContext.enqueueFrameWork(std::move(functor));
         }
 
     private:
@@ -520,6 +516,23 @@
             return env;
         }
 
+        void doUpdatePosition(jlong frameNumber, jint left, jint top,
+                jint right, jint bottom) {
+            ATRACE_NAME("Update SurfaceView position");
+
+            JNIEnv* env = jnienv();
+            jobject localref = env->NewLocalRef(mWeakRef);
+            if (CC_UNLIKELY(!localref)) {
+                jnienv()->DeleteWeakGlobalRef(mWeakRef);
+                mWeakRef = nullptr;
+                return;
+            }
+
+            env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+                    frameNumber, left, top, right, bottom);
+            env->DeleteLocalRef(localref);
+        }
+
         JavaVM* mVm;
         jobject mWeakRef;
     };
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index b7701d6..14252dc 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -144,7 +144,7 @@
         PublicFormat f) {
     switch(f) {
         case PublicFormat::JPEG:
-            return HAL_DATASPACE_JFIF;
+            return HAL_DATASPACE_V0_JFIF;
         case PublicFormat::DEPTH_POINT_CLOUD:
         case PublicFormat::DEPTH16:
             return HAL_DATASPACE_DEPTH;
@@ -156,7 +156,7 @@
         case PublicFormat::YUV_420_888:
         case PublicFormat::NV21:
         case PublicFormat::YV12:
-            return HAL_DATASPACE_JFIF;
+            return HAL_DATASPACE_V0_JFIF;
         default:
             // Most formats map to UNKNOWN
             return HAL_DATASPACE_UNKNOWN;
@@ -210,7 +210,7 @@
             switch (dataSpace) {
                 case HAL_DATASPACE_DEPTH:
                     return PublicFormat::DEPTH_POINT_CLOUD;
-                case HAL_DATASPACE_JFIF:
+                case HAL_DATASPACE_V0_JFIF:
                     return PublicFormat::JPEG;
                 default:
                     // Assume otherwise-marked blobs are also JPEG
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 612f4df..3f4b2a6 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -302,9 +302,6 @@
         return false;
     }
 
-    // Unmount storage provided by root namespace and mount requested view
-    UnmountTree("/storage");
-
     String8 storageSource;
     if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
         storageSource = "/mnt/runtime/default";
@@ -667,12 +664,24 @@
   return pid;
 }
 
+static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) {
+    // Zygote process unmount root storage space initially before every child processes are forked.
+    // Every forked child processes (include SystemServer) only mount their own root storage space
+    // And no need unmount storage operation in MountEmulatedStorage method.
+    // Zygote process does not utilize root storage spaces and unshared its mount namespace from the ART.
+
+    UnmountTree("/storage");
+    return;
+}
+
 static const JNINativeMethod gMethods[] = {
     { "nativeForkAndSpecialize",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
-      (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
+      (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
+    { "nativeUnmountStorageOnInit", "()V",
+      (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit }
 };
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6444c6c..97a51d5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2959,8 +2959,8 @@
                  android:icon="@drawable/ic_launcher_android"
                  android:supportsRtl="true"
                  android:theme="@style/Theme.Material.DayNight.DarkActionBar"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
                 android:theme="@style/Theme.DeviceDefault.Resolver"
                 android:finishOnCloseSystemDialogs="true"
diff --git a/core/res/res/anim/progress_indeterminate_rotation_material.xml b/core/res/res/anim/progress_indeterminate_rotation_material.xml
index 5d3ba22..6e12105 100644
--- a/core/res/res/anim/progress_indeterminate_rotation_material.xml
+++ b/core/res/res/anim/progress_indeterminate_rotation_material.xml
@@ -16,7 +16,7 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="6665"
+    android:duration="4444"
     android:interpolator="@android:anim/linear_interpolator"
     android:propertyName="rotation"
     android:repeatCount="-1"
diff --git a/core/res/res/drawable/vector_drawable_progress_bar_large.xml b/core/res/res/drawable/vector_drawable_progress_bar_large.xml
index cd678f1..6448f3b 100644
--- a/core/res/res/drawable/vector_drawable_progress_bar_large.xml
+++ b/core/res/res/drawable/vector_drawable_progress_bar_large.xml
@@ -16,22 +16,22 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:height="76dp"
         android:width="76dp"
-        android:viewportHeight="48"
-        android:viewportWidth="48"
+        android:viewportHeight="76"
+        android:viewportWidth="76"
         android:tint="?attr/colorControlActivated">
 
     <group
         android:name="root"
-        android:translateX="24.0"
-        android:translateY="24.0" >
+        android:translateX="38.0"
+        android:translateY="38.0" >
         <path
             android:name="progressBar"
             android:fillColor="#00000000"
-            android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38"
+            android:pathData="M0, 0 m 0, -29 a 29,29 0 1,1 0,58 a 29,29 0 1,1 0,-58"
             android:strokeColor="@color/white"
             android:strokeLineCap="square"
             android:strokeLineJoin="miter"
-            android:strokeWidth="4"
+            android:strokeWidth="6"
             android:trimPathEnd="0"
             android:trimPathOffset="0"
             android:trimPathStart="0" />
diff --git a/core/res/res/drawable/vector_drawable_progress_bar_medium.xml b/core/res/res/drawable/vector_drawable_progress_bar_medium.xml
index 7f038f4..80e3355 100644
--- a/core/res/res/drawable/vector_drawable_progress_bar_medium.xml
+++ b/core/res/res/drawable/vector_drawable_progress_bar_medium.xml
@@ -27,7 +27,7 @@
         <path
             android:name="progressBar"
             android:fillColor="#00000000"
-            android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38"
+            android:pathData="M0, 0 m 0, -18 a 18,18 0 1,1 0,36 a 18,18 0 1,1 0,-36"
             android:strokeColor="@color/white"
             android:strokeLineCap="square"
             android:strokeLineJoin="miter"
diff --git a/core/res/res/drawable/vector_drawable_progress_bar_small.xml b/core/res/res/drawable/vector_drawable_progress_bar_small.xml
index 5625788..ebb632a 100644
--- a/core/res/res/drawable/vector_drawable_progress_bar_small.xml
+++ b/core/res/res/drawable/vector_drawable_progress_bar_small.xml
@@ -16,22 +16,22 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:height="16dp"
         android:width="16dp"
-        android:viewportHeight="48"
-        android:viewportWidth="48"
+        android:viewportHeight="16"
+        android:viewportWidth="16"
         android:tint="?attr/colorControlActivated">
 
     <group
         android:name="root"
-        android:translateX="24.0"
-        android:translateY="24.0" >
+        android:translateX="8.0"
+        android:translateY="8.0" >
         <path
             android:name="progressBar"
             android:fillColor="#00000000"
-            android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38"
+            android:pathData="M0, 0 m 0, -5.9375 a 5.9375,5.9375 0 1,1 0,11.875 a 5.9375,5.9375 0 1,1 0,-11.875"
             android:strokeColor="@color/white"
             android:strokeLineCap="square"
             android:strokeLineJoin="miter"
-            android:strokeWidth="4"
+            android:strokeWidth="2.125"
             android:trimPathEnd="0"
             android:trimPathOffset="0"
             android:trimPathStart="0" />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 50c7bfb..a52c4e5 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5876,6 +5876,12 @@
         </attr>
         <!-- sets the Miter limit for a stroked path -->
         <attr name="strokeMiterLimit" format="float"/>
+        <!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
+             For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty -->
+        <attr name="fillType" format="enum">
+            <enum name="nonZero" value="0"/>
+            <enum name="evenOdd" value="1"/>
+        </attr>
     </declare-styleable>
 
     <!-- Defines the clip path used in VectorDrawables. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index d0d1d5a..5716823 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -109,13 +109,6 @@
          included in the system image. Third-party apps cannot use it.</em> -->
     <attr name="allowClearUserData" format="boolean" />
 
-    <!-- Option to let applications specify that user data should
-         never be encrypted if an Encrypted File System solution
-         is enabled. Specifically, this is an "opt-out" feature, meaning
-         that, by default, user data will be encrypted if the EFS feature
-         is enabled. -->
-    <attr name="neverEncrypt" format="boolean" />
-
     <!-- Option to indicate this application is only for testing purposes.
          For example, it may expose functionality or data outside of itself
          that would cause a security hole, but is useful for testing.  This
@@ -579,10 +572,10 @@
          single integer, with higher numbers considered to be better. -->
     <attr name="priority" format="integer" />
 
-    <!-- Indicate if this component is aware of encryption lifecycle, and can be
+    <!-- Indicate if this component is aware of direct boot lifecycle, and can be
          safely run before the user has entered their credentials (such as a lock
          pattern or PIN). -->
-    <attr name="encryptionAware" format="boolean" />
+    <attr name="directBootAware" format="boolean" />
 
     <!-- Specify how an activity should be launched.  See the
          <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
@@ -1262,7 +1255,6 @@
         <attr name="restoreNeedsApplication" />
         <attr name="restoreAnyVersion" />
         <attr name="backupInForeground" />
-        <attr name="neverEncrypt" />
         <!-- Request that your application's processes be created with
              a large Dalvik heap.  This applies to <em>all</em> processes
              created for the application.  It only applies to the first
@@ -1306,8 +1298,8 @@
         <attr name="usesCleartextTraffic" />
         <attr name="multiArch" />
         <attr name="extractNativeLibs" />
-        <attr name="forceDeviceEncrypted" format="boolean" />
-        <attr name="encryptionAware" />
+        <attr name="defaultToDeviceProtectedStorage" format="boolean" />
+        <attr name="directBootAware" />
         <attr name="resizeableActivity" />
     </declare-styleable>
     <!-- The <code>permission</code> tag declares a security permission that can be
@@ -1686,7 +1678,7 @@
         <attr name="enabled" />
         <attr name="exported" />
         <attr name="singleUser" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
     </declare-styleable>
 
     <!-- Attributes that can be supplied in an AndroidManifest.xml
@@ -1770,7 +1762,7 @@
              with it is through the Service API (binding and starting). -->
         <attr name="isolatedProcess" format="boolean" />
         <attr name="singleUser" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
         <!-- If the service is an {@link android.R.attr#isolatedProcess} service, this permits a
              client to bind to the service as if it were running it its own package.  The service
              must also be {@link android.R.attr#exported} if this flag is set. -->
@@ -1810,7 +1802,7 @@
         <attr name="enabled" />
         <attr name="exported" />
         <attr name="singleUser" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
     </declare-styleable>
 
     <!-- The <code>activity</code> tag declares an
@@ -1883,7 +1875,7 @@
         <attr name="supportsPictureInPicture" />
         <attr name="lockTaskMode" />
         <attr name="showForAllUsers" />
-        <attr name="encryptionAware" />
+        <attr name="directBootAware" />
         <!-- @hide This activity is always focusable regardless of if it is in a task/stack whose
              activities are normally not focusable.
              For example, {@link android.R.attr#supportsPictureInPicture} activities are placed
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2b0ef42..7b85c7e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2679,8 +2679,8 @@
     <public type="attr" name="contextPopupMenuStyle" />
     <public type="attr" name="textAppearancePopupMenuHeader" />
     <public type="attr" name="windowBackgroundFallback" />
-    <public type="attr" name="forceDeviceEncrypted" />
-    <public type="attr" name="encryptionAware" />
+    <public type="attr" name="defaultToDeviceProtectedStorage" />
+    <public type="attr" name="directBootAware" />
     <public type="attr" name="preferenceFragmentStyle" />
     <public type="attr" name="canControlMagnification" />
     <public type="attr" name="languageTag" />
@@ -2706,6 +2706,9 @@
     <public type="attr" name="canRecord" />
     <public type="attr" name="tunerCount" />
     <public type="attr" name="nfcAntennaPositionDrawable" />
+    <public type="attr" name="fillType" />
+    <public type="attr" name="popupEnterTransition" />
+    <public type="attr" name="popupExitTransition" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5d083d7..ba9bcaa 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2567,6 +2567,13 @@
     <!-- Title of intent resolver dialog when selecting a sharing application to run
          and a previously used application is known. -->
     <string name="whichSendApplicationNamed">Share with %1$s</string>
+    <!-- Title of intent resolver dialog when selecting an application to run to
+         send content to a specific recipient. Often used for email. -->
+    <string name="whichSendToApplication">Send using</string>
+    <!-- Title of intent resolver dialog when selecting an application to run to
+         send content to a specific recipient and a previously used application is known.
+         Often used for email. -->
+    <string name="whichSendToApplicationNamed">Send using %1$s</string>
     <!-- Title of intent resolver dialog when selecting a HOME application to run. -->
     <string name="whichHomeApplication">Select a Home app</string>
     <!-- Title of intent resolver dialog when selecting a HOME application to run
@@ -2936,8 +2943,8 @@
 
     <!-- Title of the pop-up dialog in which the user switches keyboard, also known as input method. -->
     <string name="select_input_method">Change keyboard</string>
-    <!-- Title of a button to open the settings to enable or disable keyboards, also known as input methods [CHAR LIMIT=30] -->
-    <string name="configure_input_methods">Choose keyboards</string>
+    <!-- Title of a button to open the settings to enable or disable other soft keyboards (also known as input methods) [CHAR LIMIT=30] -->
+    <string name="configure_input_methods">Other keyboards</string>
     <!-- Summary text of a toggle switch to enable/disable use of the IME while a physical
          keyboard is connected -->
     <string name="show_ime">Keep it on screen while physical keyboard is active</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index a65a813..e636bc0 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -993,7 +993,7 @@
     </style>
 
     <style name="Widget.Material.SuggestionItem" parent="@android:style/TextAppearance.Material.Body1">
-        <item name="textColor">#8a000000</item>  <!-- alpha=.54, textColor=@color/black -->
+        <item name="textColor">?attr/textColorSecondary</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
         <item name="layout_gravity">start|center_vertical</item>
@@ -1008,11 +1008,11 @@
     </style>
 
     <style name="TextAppearance.Material.TextSuggestionHighlight" parent="Widget.Material.SuggestionItem">
-        <item name="textColor">#de000000</item>  <!-- alpha=.87, textColor=@color/black -->
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="Widget.Material.SuggestionButton" parent="@android:style/TextAppearance.Material.Button">
-        <item name="textColor">#de009688</item>  <!-- alpha=.87, textColor=#009688 -->
+        <item name="textColor">?attr/colorAccent</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
         <item name="layout_gravity">start|center_vertical</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index f01cce3..8b78183 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2213,6 +2213,8 @@
   <java-symbol type="string" name="whichEditApplicationNamed" />
   <java-symbol type="string" name="whichSendApplication" />
   <java-symbol type="string" name="whichSendApplicationNamed" />
+  <java-symbol type="string" name="whichSendToApplication" />
+  <java-symbol type="string" name="whichSendToApplicationNamed" />
   <java-symbol type="attr" name="lightY" />
   <java-symbol type="attr" name="lightZ" />
   <java-symbol type="attr" name="lightRadius" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 5970a22..a361eda 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -223,6 +223,7 @@
         <item name="textSelectHandleWindowStyle">@style/Widget.Material.TextSelectHandle</item>
         <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item_material</item>
         <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container_material</item>
+        <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Material.TextSuggestionHighlight</item>
         <item name="textCursorDrawable">@drawable/text_cursor_material</item>
 
         <!-- Widget styles -->
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index bfa2b10..b780778 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -111,7 +111,7 @@
     <!-- accessibility test permissions -->
     <uses-permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT" />
 
-    <application android:theme="@style/Theme">
+    <application android:theme="@style/Theme" android:supportsRtl="true">
         <uses-library android:name="android.test.runner" />
         <uses-library android:name="org.apache.http.legacy" android:required="false" />
         <meta-data
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index cbf17a4..ec8cd71 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -37,6 +37,8 @@
 import android.print.mockservice.PrinterDiscoverySessionCallbacks;
 import android.print.mockservice.StubbablePrinterDiscoverySession;
 
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -253,6 +255,7 @@
     /**
      * test IPrintManager.getPrintJobInfo
      */
+    @LargeTest
     public void testGetPrintJobInfo() throws Exception {
         startPrinting();
 
@@ -274,6 +277,7 @@
     /**
      * test IPrintManager.getPrintJobInfos
      */
+    @LargeTest
     public void testGetPrintJobInfos() throws Exception {
         startPrinting();
 
@@ -301,6 +305,7 @@
     /**
      * test IPrintManager.print
      */
+    @LargeTest
     public void testPrint() throws Exception {
         final String name = "dummy print job";
 
@@ -354,6 +359,7 @@
     /**
      * test IPrintManager.cancelPrintJob
      */
+    @LargeTest
     public void testCancelPrintJob() throws Exception {
         startPrinting();
 
@@ -377,6 +383,7 @@
     /**
      * test IPrintManager.restartPrintJob
      */
+    @LargeTest
     public void testRestartPrintJob() throws Exception {
         startPrinting();
 
@@ -399,6 +406,7 @@
     /**
      * test IPrintManager.addPrintJobStateChangeListener
      */
+    @MediumTest
     public void testAddPrintJobStateChangeListener() throws Exception {
         final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
 
@@ -424,6 +432,7 @@
     /**
      * test IPrintManager.removePrintJobStateChangeListener
      */
+    @MediumTest
     public void testRemovePrintJobStateChangeListener() throws Exception {
         final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener();
 
@@ -447,6 +456,7 @@
     /**
      * test IPrintManager.addPrintServicesChangeListener
      */
+    @MediumTest
     public void testAddPrintServicesChangeListener() throws Exception {
         final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
 
@@ -465,6 +475,7 @@
     /**
      * test IPrintManager.removePrintServicesChangeListener
      */
+    @MediumTest
     public void testRemovePrintServicesChangeListener() throws Exception {
         final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener();
 
@@ -488,6 +499,7 @@
     /**
      * test IPrintManager.getPrintServices
      */
+    @MediumTest
     public void testGetPrintServices() throws Exception {
         List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId);
@@ -509,6 +521,7 @@
     /**
      * test IPrintManager.setPrintServiceEnabled
      */
+    @MediumTest
     public void testSetPrintServiceEnabled() throws Exception {
         final ComponentName printService = mIPrintManager.getPrintServices(
                 PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName();
@@ -548,6 +561,7 @@
     /**
      * test IPrintManager.createPrinterDiscoverySession
      */
+    @MediumTest
     public void testCreatePrinterDiscoverySession() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
@@ -573,6 +587,7 @@
     /**
      * test IPrintManager.startPrinterDiscovery
      */
+    @LargeTest
     public void testStartPrinterDiscovery() throws Exception {
         startPrinting();
 
@@ -615,6 +630,7 @@
     /**
      * test IPrintManager.stopPrinterDiscovery
      */
+    @MediumTest
     public void testStopPrinterDiscovery() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
@@ -638,6 +654,7 @@
     /**
      * test IPrintManager.validatePrinters
      */
+    @LargeTest
     public void testValidatePrinters() throws Exception {
         startPrinting();
 
@@ -678,6 +695,7 @@
     /**
      * test IPrintManager.startPrinterStateTracking
      */
+    @LargeTest
     public void testStartPrinterStateTracking() throws Exception {
         startPrinting();
 
@@ -699,6 +717,7 @@
     /**
      * test IPrintManager.getCustomPrinterIcon
      */
+    @LargeTest
     public void testGetCustomPrinterIcon() throws Exception {
         startPrinting();
 
@@ -720,6 +739,7 @@
     /**
      * test IPrintManager.stopPrinterStateTracking
      */
+    @LargeTest
     public void testStopPrinterStateTracking() throws Exception {
         startPrinting();
 
@@ -746,6 +766,7 @@
     /**
      * test IPrintManager.destroyPrinterDiscoverySession
      */
+    @MediumTest
     public void testDestroyPrinterDiscoverySession() throws Exception {
         final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver();
 
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index 3be9cfc..e1b305f 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -69,6 +69,10 @@
     public void testCombiningEnclosingKeycaps() {
         EditorState state = new EditorState();
 
+        state.setByString("'1' U+E0101 U+20E3 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
         // multiple COMBINING ENCLOSING KEYCAP
         state.setByString("'1' U+20E3 U+20E3 |");
         backspace(state, 0);
@@ -157,6 +161,19 @@
     public void testEmojiZWJSequence() {
         EditorState state = new EditorState();
 
+        // U+200D is ZERO WIDTH JOINER.
+        state.setByString("U+1F441 U+200D U+1F5E8 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+1F441 U+200D U+1F5E8 U+FE0E |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
         // End with ZERO WIDTH JOINER
         state.setByString("U+1F441 U+200D |");
         backspace(state, 0);
@@ -224,6 +241,11 @@
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
+        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+        state.setByString("U+1F466 U+1F3FB |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
         // Isolated emoji modifier
         state.setByString("U+1F3FB |");
         backspace(state, 0);
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index f7dab2d..0fed77c 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -137,6 +137,15 @@
     public void testEmojiZeroWidthJoinerSequence() {
         EditorState state = new EditorState();
 
+        // U+200D is ZERO WIDTH JOINER.
+        state.setByString("| U+1F441 U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
         // End with ZERO WIDTH JOINER
         state.setByString("| U+1F441 U+200D");
         forwardDelete(state, 0);
@@ -188,6 +197,11 @@
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
+        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+        state.setByString("| U+1F466 U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
         // Isolated emoji modifier
         state.setByString("| U+1F3FB");
         forwardDelete(state, 0);
diff --git a/core/tests/coretests/src/android/widget/EditorCursorTest.java b/core/tests/coretests/src/android/widget/EditorCursorTest.java
index 04c8b8c..6d650ff 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorTest.java
@@ -16,16 +16,34 @@
 
 package android.widget;
 
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.view.Choreographer;
 import android.view.ViewGroup;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnLeft;
+import static android.widget.espresso.TextViewAssertions.hasInsertionPointerOnRight;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.isEmptyString;
+import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.Matchers.sameInstance;
+
 public class EditorCursorTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
 
+
+    private final static String LTR_STRING = "aaaaaaaaaaaaaaaaaaaaaa";
+    private final static String LTR_HINT = "hint";
+    private final static String RTL_STRING = "مرحبا الروبوت مرحبا الروبوت مرحبا الروبوت";
+    private final static String RTL_HINT = "الروبوت";
+    private final static int CURSOR_BLINK_MS = 500;
+
     private EditText mEditText;
-    private final String RTL_STRING = "مرحبا الروبوت مرحبا الروبوت مرحبا الروبوت";
 
     public EditorCursorTest() {
         super(TextViewActivity.class);
@@ -55,110 +73,160 @@
             @Override
             public void run() {
                 getActivity().setContentView(layout);
-                mEditText.requestFocus();
             }
         });
         getInstrumentation().waitForIdleSync();
+        onView(sameInstance(mEditText)).perform(click());
     }
 
     @SmallTest
-    public void testCursorIsInViewBoundariesWhenOnRightForLtr() throws Exception {
+    public void testCursorIsInViewBoundariesWhenOnRightForLtr() {
         // Asserts that when an EditText has LTR text, and cursor is at the end (right),
         // cursor is drawn to the right edge of the view
-        getActivity().runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mEditText.setText("aaaaaaaaaaaaaaaaaaaaaa");
-                int length = mEditText.getText().length();
-                mEditText.setSelection(length, length);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
+        setEditTextText(LTR_STRING, LTR_STRING.length());
 
-        Editor editor = mEditText.getEditorForTesting();
-        Drawable drawable = editor.getCursorDrawable()[0];
-        Rect drawableBounds = drawable.getBounds();
-        Rect drawablePadding = new Rect();
-        drawable.getPadding(drawablePadding);
-
-        // right edge of the view including the scroll
-        int maxRight = mEditText.getWidth() - mEditText.getCompoundPaddingRight()
-                - mEditText.getCompoundPaddingLeft() + +mEditText.getScrollX();
-        int diff = drawableBounds.right - drawablePadding.right - maxRight;
-        assertTrue(diff >= 0 && diff <= 1);
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
     }
 
     @SmallTest
-    public void testCursorIsInViewBoundariesWhenOnLeftForLtr() throws Exception {
+    public void testCursorIsInViewBoundariesWhenOnLeftForLtr() {
         // Asserts that when an EditText has LTR text, and cursor is at the beginning,
         // cursor is drawn to the left edge of the view
+        setEditTextText(LTR_STRING, 0);
 
-        getActivity().runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mEditText.setText("aaaaaaaaaaaaaaaaaaaaaa");
-                mEditText.setSelection(0, 0);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
-
-        Drawable drawable = mEditText.getEditorForTesting().getCursorDrawable()[0];
-        Rect drawableBounds = drawable.getBounds();
-        Rect drawablePadding = new Rect();
-        drawable.getPadding(drawablePadding);
-
-        int diff = drawableBounds.left + drawablePadding.left;
-        assertTrue(diff >= 0 && diff <= 1);
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
     }
 
     @SmallTest
-    public void testCursorIsInViewBoundariesWhenOnRightForRtl() throws Exception {
+    public void testCursorIsInViewBoundariesWhenOnRightForRtl() {
         // Asserts that when an EditText has RTL text, and cursor is at the end,
         // cursor is drawn to the left edge of the view
+        setEditTextText(RTL_STRING, 0);
 
-        getActivity().runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mEditText.setText(RTL_STRING);
-                mEditText.setSelection(0, 0);
-            }
-        });
-        getInstrumentation().waitForIdleSync();
-
-        Drawable drawable = mEditText.getEditorForTesting().getCursorDrawable()[0];
-        Rect drawableBounds = drawable.getBounds();
-        Rect drawablePadding = new Rect();
-        drawable.getPadding(drawablePadding);
-
-        int maxRight = mEditText.getWidth() - mEditText.getCompoundPaddingRight()
-                - mEditText.getCompoundPaddingLeft() + mEditText.getScrollX();
-
-        int diff = drawableBounds.right - drawablePadding.right - maxRight;
-        assertTrue(diff >= 0 && diff <= 1);
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
     }
 
     @SmallTest
-    public void testCursorIsInViewBoundariesWhenOnLeftForRtl() throws Exception {
+    public void testCursorIsInViewBoundariesWhenOnLeftForRtl() {
         // Asserts that when an EditText has RTL text, and cursor is at the beginning,
         // cursor is drawn to the right edge of the view
+        setEditTextText(RTL_STRING, RTL_STRING.length());
 
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+    }
+
+    /* Tests for cursor positioning with hint */
+    @SmallTest
+    public void testCursorIsOnLeft_withFirstStrongLtrAlgorithm() {
+        setEditTextHint(null, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+        assertThat(mEditText.getHint(), nullValue());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+        setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+        setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_LTR, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+    }
+
+    @SmallTest
+    public void testCursorIsOnRight_withFirstStrongRtlAlgorithm() {
+        setEditTextHint(null, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+        assertThat(mEditText.getHint(), nullValue());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+        setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+        setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_FIRST_STRONG_RTL, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+    }
+
+    @SmallTest
+    public void testCursorIsOnLeft_withLtrAlgorithm() {
+        setEditTextHint(null, TextView.TEXT_DIRECTION_LTR, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+        assertThat(mEditText.getHint(), nullValue());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+        setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_LTR, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+
+        setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_LTR, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnLeft());
+    }
+
+    @SmallTest
+    public void testCursorIsOnRight_withRtlAlgorithm() {
+        setEditTextHint(null, TextView.TEXT_DIRECTION_RTL, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+        assertThat(mEditText.getHint(), nullValue());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+        setEditTextHint(LTR_HINT, TextView.TEXT_DIRECTION_RTL, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+
+        setEditTextHint(RTL_HINT, TextView.TEXT_DIRECTION_RTL, 0);
+        assertThat(mEditText.getText().toString(), isEmptyString());
+
+        onView(sameInstance(mEditText)).check(hasInsertionPointerOnRight());
+    }
+
+    private void setEditTextProperties(final String text, final String hint,
+            final Integer textDirection, final Integer selection) {
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                mEditText.setText(RTL_STRING);
-                int length = mEditText.getText().length();
-                mEditText.setSelection(length, length);
+                if (textDirection != null) mEditText.setTextDirection(textDirection);
+                if (text != null) mEditText.setText(text);
+                if (hint != null) mEditText.setHint(hint);
+                if (selection != null) mEditText.setSelection(selection);
             }
         });
         getInstrumentation().waitForIdleSync();
 
-        Drawable drawable = mEditText.getEditorForTesting().getCursorDrawable()[0];
-        Rect drawableBounds = drawable.getBounds();
-        Rect drawablePadding = new Rect();
-        drawable.getPadding(drawablePadding);
-
-        int diff = drawableBounds.left - mEditText.getScrollX() + drawablePadding.left;
-        assertTrue(diff >= 0 && diff <= 1);
+        // wait for cursor to be drawn. updateCursorPositions function is called during draw() and
+        // only when cursor is visible during blink.
+        final CountDownLatch latch = new CountDownLatch(1);
+        mEditText.postOnAnimationDelayed(new Runnable() {
+            @Override
+            public void run() {
+                latch.countDown();
+            }
+        }, CURSOR_BLINK_MS);
+        try {
+            assertThat("Problem while waiting for the cursor to blink",
+                    latch.await(10, TimeUnit.SECONDS), equalTo(true));
+        } catch (Exception e) {
+            fail("Problem while waiting for the cursor to blink");
+        }
     }
 
+    private void setEditTextHint(final String hint, final int textDirection, final int selection) {
+        setEditTextProperties(null, hint, textDirection, selection);
+    }
+
+    private void setEditTextText(final String text, final Integer selection) {
+        setEditTextProperties(text, null, null, selection);
+    }
 }
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 4a4727f..91d57e7 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -16,8 +16,10 @@
 
 package android.widget;
 
+import static android.support.test.espresso.action.ViewActions.longClick;
 import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
 import static android.widget.espresso.DragHandleUtils.onHandleView;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem;
 import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
 import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
 import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex;
@@ -49,6 +51,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.Selection;
 import android.text.Spannable;
+import android.text.InputType;
 import android.view.KeyEvent;
 
 import static org.hamcrest.Matchers.anyOf;
@@ -234,6 +237,33 @@
     }
 
     @SmallTest
+    public void testToolbarAppearsAfterSelection_withFirstStringLtrAlgorithmAndRtlHint()
+            throws Exception {
+        // after the hint layout change, the floating toolbar was not visible in the case below
+        // this test tests that the floating toolbar is displayed on the screen and is visible to
+        // user.
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        textView.post(new Runnable() {
+            @Override
+            public void run() {
+                textView.setTextDirection(TextView.TEXT_DIRECTION_FIRST_STRONG_LTR);
+                textView.setInputType(InputType.TYPE_CLASS_TEXT);
+                textView.setSingleLine(true);
+                textView.setHint("الروبوت");
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test"));
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1));
+        onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click());
+        onView(withId(R.id.textview)).perform(longClick());
+        sleepForFloatingToolbarPopup();
+
+        assertFloatingToolbarIsDisplayed();
+    }
+
+    @SmallTest
     public void testToolbarAndInsertionHandle() throws Exception {
         final String text = "text";
         onView(withId(R.id.textview)).perform(click());
diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
index f02fe00..0f7f359 100644
--- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
@@ -54,6 +54,16 @@
     }
 
     /**
+     * Creates a {@link ViewInteraction} for the floating bar menu item with the given matcher.
+     *
+     * @param matcher The matcher for the menu item.
+     */
+    public static ViewInteraction onFloatingToolBarItem(Matcher<View> matcher) {
+        return onView(matcher)
+                .inRoot(withDecorView(hasDescendant(withTagValue(is(TAG)))));
+    }
+
+    /**
      * Asserts that the floating toolbar is displayed on screen.
      *
      * @throws AssertionError if the assertion fails
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
index 37c7425..6e44cd8 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
@@ -19,15 +19,23 @@
 import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.number.IsCloseTo.closeTo;
 
+import android.annotation.IntDef;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.support.test.espresso.NoMatchingViewException;
 import android.support.test.espresso.ViewAssertion;
 import android.view.View;
+import android.widget.EditText;
 import android.widget.TextView;
 
 import junit.framework.AssertionFailedError;
 import org.hamcrest.Matcher;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A collection of assertions on a {@link android.widget.TextView}.
  */
@@ -113,6 +121,22 @@
     }
 
     /**
+     * Returns a {@link ViewAssertion} that asserts that the EditText insertion pointer is on
+     * the left edge.
+     */
+    public static ViewAssertion hasInsertionPointerOnLeft() {
+        return new CursorPositionAssertion(CursorPositionAssertion.LEFT);
+    }
+
+    /**
+     * Returns a {@link ViewAssertion} that asserts that the EditText insertion pointer is on
+     * the right edge.
+     */
+    public static ViewAssertion hasInsertionPointerOnRight() {
+        return new CursorPositionAssertion(CursorPositionAssertion.RIGHT);
+    }
+
+    /**
      * A {@link ViewAssertion} to check the selected text in a {@link TextView}.
      */
     private static final class TextSelectionAssertion implements ViewAssertion {
@@ -142,4 +166,54 @@
             }
         }
     }
+
+    /**
+     * {@link ViewAssertion} to check that EditText cursor is on a given position.
+     */
+    static class CursorPositionAssertion implements ViewAssertion {
+
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({LEFT, RIGHT})
+        public @interface CursorEdgePositionType {}
+        public static final int LEFT = 0;
+        public static final int RIGHT = 1;
+
+        private final int mPosition;
+
+        private CursorPositionAssertion(@CursorEdgePositionType int position) {
+            this.mPosition = position;
+        }
+
+        @Override
+        public void check(View view, NoMatchingViewException exception) {
+            if (!(view instanceof EditText)) {
+                throw new AssertionFailedError("View should be an instance of EditText");
+            }
+            EditText editText = (EditText) view;
+            Drawable drawable = editText.getEditorForTesting().getCursorDrawable()[0];
+            Rect drawableBounds = drawable.getBounds();
+            Rect drawablePadding = new Rect();
+            drawable.getPadding(drawablePadding);
+
+            final int diff;
+            final String positionStr;
+            switch (mPosition) {
+                case LEFT:
+                    positionStr = "left";
+                    diff = drawableBounds.left - editText.getScrollX() + drawablePadding.left;
+                    break;
+                case RIGHT:
+                    positionStr = "right";
+                    int maxRight = editText.getWidth() - editText.getCompoundPaddingRight()
+                            - editText.getCompoundPaddingLeft() + editText.getScrollX();
+                    diff = drawableBounds.right - drawablePadding.right - maxRight;
+                    break;
+                default:
+                    throw new AssertionFailedError("Unknown position for cursor assertion");
+            }
+
+            assertThat("Cursor should be on the " + positionStr, Double.valueOf(diff),
+                    closeTo(0f, 1f));
+        }
+    }
 }
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index dc85046..fd28f64 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -105,4 +105,4 @@
 .PHONY: fontchain_lint
 fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
 	PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
-	python $(FONTCHAIN_LINTER) $(TARGET_OUT)
\ No newline at end of file
+	python $(FONTCHAIN_LINTER) $(TARGET_OUT) external/unicode
diff --git a/docs/html/guide/topics/graphics/hardware-accel.jd b/docs/html/guide/topics/graphics/hardware-accel.jd
index e3f1d9e..ca7255b 100644
--- a/docs/html/guide/topics/graphics/hardware-accel.jd
+++ b/docs/html/guide/topics/graphics/hardware-accel.jd
@@ -284,7 +284,7 @@
     </tr>
     <tr>
         <td class="label_neg">drawPicture()</td>
-        <td class="value_neg">23</td>
+        <td class="value_pos">23</td>
     </tr>
     <tr>
         <td class="label_pos">drawPosText()</td>
@@ -421,14 +421,6 @@
         <td colspan="5" class="s5">Xfermode</td>
     </tr>
     <tr>
-        <td class="label_neg">AvoidXfermode</td>
-        <td class="value_neg">&#10007;</td>
-    </tr>
-    <tr>
-        <td class="label_neg">PixelXorXfermode</td>
-        <td class="value_neg">&#10007;</td>
-    </tr>
-    <tr>
         <td class="label_neg">PorterDuff.Mode.DARKEN (framebuffer)</td>
         <td class="value_neg">&#10007;</td>
     </tr>
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3e86e6f..3973f2f 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -17,10 +17,13 @@
 package android.graphics;
 
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Defines a simple shape, used for bounding graphical regions.
  * <p>
@@ -34,11 +37,28 @@
 public final class Outline {
     private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
 
-    /** @hide */
-    public Path mPath;
+    private static final int MODE_EMPTY = 0;
+    private static final int MODE_RECT = 1;
+    private static final int MODE_CONVEX_PATH = 2;
 
     /** @hide */
-    public Rect mRect;
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = false,
+            value = {
+                    MODE_EMPTY,
+                    MODE_RECT,
+                    MODE_CONVEX_PATH,
+            })
+    public @interface Mode {}
+
+    @Mode
+    private int mMode = MODE_EMPTY;
+
+    /** @hide */
+    public final Path mPath = new Path();
+
+    /** @hide */
+    public final Rect mRect = new Rect();
     /** @hide */
     public float mRadius = RADIUS_UNDEFINED;
     /** @hide */
@@ -63,8 +83,9 @@
      * @see #isEmpty()
      */
     public void setEmpty() {
-        mPath = null;
-        mRect = null;
+        mMode = MODE_EMPTY;
+        mPath.rewind();
+        mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
 
@@ -77,7 +98,7 @@
      * @see #setEmpty()
      */
     public boolean isEmpty() {
-        return mRect == null && mPath == null;
+        return mMode == MODE_EMPTY;
     }
 
 
@@ -90,7 +111,7 @@
      * @see {@link android.view.View#setClipToOutline(boolean)}
      */
     public boolean canClip() {
-        return !isEmpty() && mRect != null;
+        return mMode != MODE_CONVEX_PATH;
     }
 
     /**
@@ -122,19 +143,9 @@
      * @param src Source outline to copy from.
      */
     public void set(@NonNull Outline src) {
-        if (src.mPath != null) {
-            if (mPath == null) {
-                mPath = new Path();
-            }
-            mPath.set(src.mPath);
-            mRect = null;
-        }
-        if (src.mRect != null) {
-            if (mRect == null) {
-                mRect = new Rect();
-            }
-            mRect.set(src.mRect);
-        }
+        mMode = src.mMode;
+        mPath.set(src.mPath);
+        mRect.set(src.mRect);
         mRadius = src.mRadius;
         mAlpha = src.mAlpha;
     }
@@ -165,10 +176,10 @@
             return;
         }
 
-        if (mRect == null) mRect = new Rect();
+        mMode = MODE_RECT;
         mRect.set(left, top, right, bottom);
         mRadius = radius;
-        mPath = null;
+        mPath.rewind();
     }
 
     /**
@@ -188,7 +199,7 @@
      *         bounds, or {@code false} if no outline bounds are set
      */
     public boolean getRect(@NonNull Rect outRect) {
-        if (mRect == null) {
+        if (mMode != MODE_RECT) {
             return false;
         }
         outRect.set(mRect);
@@ -221,10 +232,10 @@
             return;
         }
 
-        if (mPath == null) mPath = new Path();
-        mPath.reset();
+        mMode = MODE_CONVEX_PATH;
+        mPath.rewind();
         mPath.addOval(left, top, right, bottom, Path.Direction.CW);
-        mRect = null;
+        mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
 
@@ -248,10 +259,10 @@
         if (!convexPath.isConvex()) {
             throw new IllegalArgumentException("path must be convex");
         }
-        if (mPath == null) mPath = new Path();
 
+        mMode = MODE_CONVEX_PATH;
         mPath.set(convexPath);
-        mRect = null;
+        mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
 
@@ -259,9 +270,9 @@
      * Offsets the Outline by (dx,dy)
      */
     public void offset(int dx, int dy) {
-        if (mRect != null) {
+        if (mMode == MODE_RECT) {
             mRect.offset(dx, dy);
-        } else if (mPath != null) {
+        } else if (mMode == MODE_CONVEX_PATH) {
             mPath.offset(dx, dy);
         }
     }
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 0cde0b9..93ef3f0 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -30,6 +30,11 @@
  * These fields can be accessed directly. Use width() and height() to retrieve
  * the rectangle's width and height. Note: most methods do not check to see that
  * the coordinates are sorted correctly (i.e. left <= right and top <= bottom).
+ * <p>
+ * Note that the right and bottom coordinates are exclusive. This means a Rect
+ * being drawn untransformed onto a {@link android.graphics.Canvas} will draw
+ * into the column and row described by its left and top coordinates, but not
+ * those of its bottom and right.
  */
 public final class Rect implements Parcelable {
     public int left;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index ae98c22..bd069ff 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -1281,8 +1281,10 @@
         private static final int STROKE_LINE_CAP_INDEX = 8;
         private static final int STROKE_LINE_JOIN_INDEX = 9;
         private static final int STROKE_MITER_LIMIT_INDEX = 10;
-        private static final int TOTAL_PROPERTY_COUNT = 11;
+        private static final int FILL_TYPE_INDEX = 11;
+        private static final int TOTAL_PROPERTY_COUNT = 12;
 
+        // Property map for animatable attributes.
         private final static HashMap<String, Integer> sPropertyMap
                 = new HashMap<String, Integer> () {
             {
@@ -1399,6 +1401,7 @@
             int strokeLineCap =  properties.getInt(STROKE_LINE_CAP_INDEX * 4);
             int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4);
             float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4);
+            int fillType = properties.getInt(FILL_TYPE_INDEX * 4);
             Shader fillGradient = null;
             Shader strokeGradient = null;
             // Account for any configuration changes.
@@ -1474,10 +1477,11 @@
                     R.styleable.VectorDrawablePath_trimPathOffset, trimPathOffset);
             trimPathStart = a.getFloat(
                     R.styleable.VectorDrawablePath_trimPathStart, trimPathStart);
+            fillType = a.getInt(R.styleable.VectorDrawablePath_fillType, fillType);
 
             nUpdateFullPathProperties(mNativePtr, strokeWidth, strokeColor, strokeAlpha,
                     fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset,
-                    strokeMiterLimit, strokeLineCap, strokeLineJoin);
+                    strokeMiterLimit, strokeLineCap, strokeLineJoin, fillType);
         }
 
         @Override
@@ -1645,7 +1649,7 @@
     private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
             int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
             float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
-            int strokeLineJoin);
+            int strokeLineJoin, int fillType);
     private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
     private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
 
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index bb3ea3f..20f102b 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -198,8 +198,9 @@
 
     LOG_ALWAYS_FATAL_IF(mRenderTarget.frameBufferId != 0, "decoration only supported for FBO 0");
     // TODO: Currently assume full FBO damage, due to FrameInfoVisualizer::unionDirty.
-    // Should should scissor safely.
+    // Should should scissor/set mHasDrawn safely.
     mRenderState.scissor().setEnabled(false);
+    mHasDrawn = true;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
             .setRoundRectClipState(nullptr)
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 330dc29..eac9359 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -92,6 +92,8 @@
      */
     bool init();
 
+    bool isInitialized() { return mInitialized; }
+
     /**
      * Flush the cache.
      *
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index fd5856a..50b21a4 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -646,7 +646,9 @@
 }
 
 void FrameBuilder::deferTextOp(const TextOp& op) {
-    BakedOpState* bakedState = tryBakeOpState(op);
+    BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
+            mAllocator, *mCanvasState.writableSnapshot(), op,
+            BakedOpState::StrokeBehavior::StyleDefined);
     if (!bakedState) return; // quick rejected
 
     batchid_t batchId = textBatchId(*(op.paint));
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 114347d..cdbbbab 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -197,7 +197,12 @@
 }
 
 void Layer::clearTexture() {
-    caches.textureState().unbindTexture(texture.mId);
+    // There's a rare possibility that Caches could have been destroyed already
+    // since this method is queued up as a task.
+    // Since this is a reset method, treat this as non-fatal.
+    if (caches.isInitialized()) {
+        caches.textureState().unbindTexture(texture.mId);
+    }
     texture.mId = 0;
 }
 
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f7b38e3..d35f764 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -158,7 +158,8 @@
 
 void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
         SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
-        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) {
+        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
+        int fillType) {
     mProperties.strokeWidth = strokeWidth;
     mProperties.strokeColor = strokeColor;
     mProperties.strokeAlpha = strokeAlpha;
@@ -167,6 +168,7 @@
     mProperties.strokeMiterLimit = strokeMiterLimit;
     mProperties.strokeLineCap = strokeLineCap;
     mProperties.strokeLineJoin = strokeLineJoin;
+    mProperties.fillType = fillType;
 
     // If any trim property changes, mark trim dirty and update the trim path
     setTrimPathStart(trimPathStart);
@@ -179,7 +181,7 @@
     return SkColorSetA(color, alphaBytes * alpha);
 }
 
-void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale,
+void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale,
                         const SkMatrix& matrix){
     // Draw path's fill, if fill color or gradient is valid
     bool needsFill = false;
@@ -196,6 +198,8 @@
     if (needsFill) {
         mPaint.setStyle(SkPaint::Style::kFill_Style);
         mPaint.setAntiAlias(true);
+        SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType);
+        renderPath.setFillType(ft);
         outCanvas->drawPath(renderPath, mPaint);
     }
 
@@ -306,7 +310,7 @@
     }
 }
 
-void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
         float strokeScale, const SkMatrix& matrix){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 36a8aeb..4d2fed0 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -96,7 +96,7 @@
 
 protected:
     virtual const SkPath& getUpdatedPath();
-    virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
+    virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) = 0;
     Data mData;
     SkPath mSkPath;
@@ -118,6 +118,7 @@
     int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
     int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
     float strokeMiterLimit = 4;
+    int fillType = 0; /* non-zero or kWinding_FillType in Skia */
 };
 
     FullPath(const FullPath& path); // for cloning
@@ -133,7 +134,7 @@
     void updateProperties(float strokeWidth, SkColor strokeColor,
             float strokeAlpha, SkColor fillColor, float fillAlpha,
             float trimPathStart, float trimPathEnd, float trimPathOffset,
-            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
+            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
     // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
     float getStrokeWidth() {
         return mProperties.strokeWidth;
@@ -197,7 +198,7 @@
 
 protected:
     const SkPath& getUpdatedPath() override;
-    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) override;
 
 private:
@@ -213,6 +214,7 @@
         StrokeLineCap,
         StrokeLineJoin,
         StrokeMiterLimit,
+        FillType,
         Count,
     };
     // Applies trimming to the specified path.
@@ -233,7 +235,7 @@
     ClipPath(const Data& nodes) : Path(nodes) {}
 
 protected:
-    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) override;
 };
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a496b49..c539d63 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,6 +484,8 @@
     bool drew = mCanvas->finish();
 #endif
 
+    waitOnFences();
+
     GL_CHECKPOINT(LOW);
 
     // Even if we decided to cancel the frame, from the perspective of jank
@@ -726,6 +728,37 @@
 #endif
 }
 
+void CanvasContext::waitOnFences() {
+    if (mFrameFences.size()) {
+        ATRACE_CALL();
+        for (auto& fence : mFrameFences) {
+            fence->getResult();
+        }
+        mFrameFences.clear();
+    }
+}
+
+class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> {
+public:
+    FuncTaskProcessor(Caches& caches)
+            : TaskProcessor<bool>(&caches.tasks) {}
+
+    virtual void onProcess(const sp<Task<bool> >& task) override {
+        FuncTask* t = static_cast<FuncTask*>(task.get());
+        t->func();
+        task->setResult(true);
+    }
+};
+
+void CanvasContext::enqueueFrameWork(std::function<void()>&& func) {
+    if (!mFrameWorkProcessor.get()) {
+        mFrameWorkProcessor = new FuncTaskProcessor(Caches::getInstance());
+    }
+    sp<FuncTask> task(new FuncTask());
+    task->func = func;
+    mFrameWorkProcessor->add(task);
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index cb61e51..6706c30 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -24,6 +24,8 @@
 #include "IContextFactory.h"
 #include "LayerUpdateQueue.h"
 #include "RenderNode.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
 #include "utils/RingBuffer.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
@@ -41,6 +43,7 @@
 #include <utils/Functor.h>
 #include <gui/Surface.h>
 
+#include <functional>
 #include <set>
 #include <string>
 #include <vector>
@@ -159,6 +162,9 @@
         }
     }
 
+    // Used to queue up work that needs to be completed before this frame completes
+    ANDROID_API void enqueueFrameWork(std::function<void()>&& func);
+
 private:
     friend class RegisterFrameCallbackTask;
     // TODO: Replace with something better for layer & other GL object
@@ -170,6 +176,8 @@
 
     void freePrefetechedLayers();
 
+    void waitOnFences();
+
     EGLint mLastFrameWidth = 0;
     EGLint mLastFrameHeight = 0;
 
@@ -213,6 +221,16 @@
 
     // Stores the bounds of the main content.
     Rect mContentDrawBounds;
+
+    // TODO: This is really a Task<void> but that doesn't really work
+    // when Future<> expects to be able to get/set a value
+    struct FuncTask : public Task<bool> {
+        std::function<void()> func;
+    };
+    class FuncTaskProcessor;
+
+    std::vector< sp<FuncTask> > mFrameFences;
+    sp<TaskProcessor<bool> > mFrameWorkProcessor;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/tests/scripts/prep_volantis.sh b/libs/hwui/tests/scripts/prep_volantis.sh
index 09d4869..0572ee55 100755
--- a/libs/hwui/tests/scripts/prep_volantis.sh
+++ b/libs/hwui/tests/scripts/prep_volantis.sh
@@ -49,6 +49,6 @@
 # 684000 708000 756000 804000 852000 (kHz)
 
 S=324000000
-echo "set gpu to $s hz"
+echo "set gpu to $S hz"
 adb shell "echo 1 > /d/clock/override.gbus/state"
 adb shell "echo $S > /d/clock/override.gbus/rate"
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index f147fd4..31555f2 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -316,6 +316,61 @@
             << "Expect number of ops = 2 * loop count";
 }
 
+static auto styles = {
+        SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style };
+
+TEST(FrameBuilder, textStyle) {
+    class TextStyleTestRenderer : public TestRendererBase {
+    public:
+        void onMergedTextOps(const MergedBakedOpList& opList) override {
+            ASSERT_EQ(0, mIndex);
+            ASSERT_EQ(3u, opList.count);
+            mIndex += opList.count;
+
+            int index = 0;
+            for (auto style : styles) {
+                auto state = opList.states[index++];
+                ASSERT_EQ(style, state->op->paint->getStyle())
+                        << "Remainder of validation relies upon stable merged order";
+                ASSERT_EQ(0, state->computedState.clipSideFlags)
+                        << "Clipped bounds validation requires unclipped ops";
+            }
+
+            Rect fill = opList.states[0]->computedState.clippedBounds;
+            Rect stroke = opList.states[1]->computedState.clippedBounds;
+            EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds)
+                    << "Stroke+Fill should be same as stroke";
+
+            EXPECT_TRUE(stroke.contains(fill));
+            EXPECT_FALSE(fill.contains(stroke));
+
+            Rect outsetFill(fill);
+            outsetFill.outset(10);
+            EXPECT_EQ(stroke, outsetFill);
+        }
+    };
+    auto node = TestUtils::createNode(0, 0, 400, 400,
+            [](RenderProperties& props, TestCanvas& canvas) {
+        SkPaint paint;
+        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+        paint.setAntiAlias(true);
+        paint.setTextSize(50);
+        paint.setStrokeWidth(10);
+
+        // draw 3 copies of the same text overlapping, each with a different style.
+        // They'll get merged, but with
+        for (auto style : styles) {
+            paint.setStyle(style);
+            TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100);
+        }
+    });
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+            TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+    TextStyleTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops";
+}
+
 RENDERTHREAD_TEST(FrameBuilder, textureLayer) {
     class TextureLayerTestRenderer : public TestRendererBase {
     public:
diff --git a/libs/hwui/tests/unit/GlopBuilderTests.cpp b/libs/hwui/tests/unit/GlopBuilderTests.cpp
index 949c541..454011f 100644
--- a/libs/hwui/tests/unit/GlopBuilderTests.cpp
+++ b/libs/hwui/tests/unit/GlopBuilderTests.cpp
@@ -16,7 +16,6 @@
 
 #include <gtest/gtest.h>
 
-#include "BakedOpRenderer.h"
 #include "Glop.h"
 #include "GlopBuilder.h"
 #include "Rect.h"
diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h
index 6cb23e5..0a7acb0 100644
--- a/libs/hwui/thread/Barrier.h
+++ b/libs/hwui/thread/Barrier.h
@@ -33,11 +33,6 @@
         mCondition.signal(mType);
     }
 
-    void close() {
-        Mutex::Autolock l(mLock);
-        mOpened = false;
-    }
-
     void wait() const {
         Mutex::Autolock l(mLock);
         while (!mOpened) {
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 11fecfb..17ce533 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -47,7 +47,6 @@
     private double mCarrierPhaseUncertainty;
     private int mMultipathIndicator;
     private double mSnrInDb;
-    private boolean mPseudorangeRateCorrected;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -58,7 +57,10 @@
     private static final int HAS_CARRIER_PHASE = (1<<11);
     private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
 
-    /** The status of multipath. */
+    /**
+     * The status of the multipath indicator.
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
         MULTIPATH_INDICATOR_NOT_USED})
@@ -440,25 +442,6 @@
     }
 
     /**
-     * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
-     *
-     * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
-     *         value, {@code false} if it contains an uncorrected value.
-     */
-    public boolean isPseudorangeRateCorrected() {
-        return mPseudorangeRateCorrected;
-    }
-
-    /**
-     * Sets whether the pseudorange corrected.
-     * @hide
-     */
-    @TestApi
-    public void setPseudorangeRateCorrected(boolean value) {
-        mPseudorangeRateCorrected = value;
-    }
-
-    /**
      * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
      * The uncertainty is represented as an absolute (single sided) value.
      */
@@ -813,7 +796,6 @@
             gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
             gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
-            gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
 
             return gnssMeasurement;
         }
@@ -845,7 +827,6 @@
         parcel.writeDouble(mCarrierPhaseUncertainty);
         parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
-        parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
     }
 
     @Override
@@ -880,10 +861,6 @@
                 mPseudorangeRateMetersPerSecond,
                 "PseudorangeRateUncertaintyMetersPerSecond",
                 mPseudorangeRateUncertaintyMetersPerSecond));
-        builder.append(String.format(
-                format,
-                "PseudorangeRateIsCorrected",
-                isPseudorangeRateCorrected()));
 
         builder.append(String.format(
                 format,
@@ -943,7 +920,6 @@
         resetCarrierPhaseUncertainty();
         setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
         resetSnrInDb();
-        setPseudorangeRateCorrected(false);
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index 86841ff..ec252a8 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -33,7 +33,10 @@
  * Events are delivered to registered instances of {@link Callback}.
  */
 public final class GnssMeasurementsEvent implements Parcelable {
-    /** The status of GNSS measurements event. */
+    /**
+     * The status of the GNSS measurements event.
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
     public @interface GnssMeasurementsStatus {}
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index ac255c8..a5eace8 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -33,7 +33,10 @@
 
     private static final byte[] EMPTY_ARRAY = new byte[0];
 
-    /** The type of the GPS Clock. */
+    /**
+     * The type of the GPS Clock.
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
         TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F})
@@ -286,18 +289,11 @@
             navigationMessage.setSvid(parcel.readInt());
             navigationMessage.setMessageId(parcel.readInt());
             navigationMessage.setSubmessageId(parcel.readInt());
-
             int dataLength = parcel.readInt();
             byte[] data = new byte[dataLength];
             parcel.readByteArray(data);
             navigationMessage.setData(data);
-
-            if (parcel.dataAvail() >= Integer.SIZE) {
-                int status = parcel.readInt();
-                navigationMessage.setStatus(status);
-            } else {
-                navigationMessage.setStatus(STATUS_UNKNOWN);
-            }
+            navigationMessage.setStatus(parcel.readInt());
 
             return navigationMessage;
         }
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 0df730d..992dfc3 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -30,7 +30,10 @@
  * Events are delivered to registered instances of {@link Callback}.
  */
 public final class GnssNavigationMessageEvent implements Parcelable {
-    /** The status of GPS measurements event. */
+    /**
+     * The status of GPS measurements event.
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
     public @interface GnssNavigationMessageStatus {}
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 2a42fc6..9c509d6 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -41,7 +41,10 @@
     /** Constellation type constant for Galileo. */
     public static final int CONSTELLATION_GALILEO = 6;
 
-    /** Constellation type. */
+    /**
+     * Constellation type.
+     * @hide
+     */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS,
             CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO})
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index 4d0d1bd..50f0bad 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -891,7 +891,7 @@
             l.mSpeed = in.readFloat();
             l.mBearing = in.readFloat();
             l.mAccuracy = in.readFloat();
-            l.mExtras = in.readBundle();
+            l.mExtras = Bundle.setDefusable(in.readBundle(), true);
             return l;
         }
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d179171..3c42161 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1076,9 +1076,6 @@
      * <p>
      * This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
-     * <p>From N onward, stream mute changes that would toggle Do Not Disturb are not allowed unless
-     * the app has been granted Do Not Disturb Access.
-     * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * <p>
      * This method was deprecated in API level 22. Prior to API level 22 this
      * method had significantly different behavior and should be used carefully.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 0f82cfc..ca306cc 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -228,7 +228,7 @@
     /**
      * Audio session ID
      */
-    private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+    private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
     /**
      * AudioAttributes
      */
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index c5d1120..e1dab09 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -295,7 +295,7 @@
     /**
      * Audio session ID
      */
-    private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+    private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
     /**
      * Reference to the app-ops service.
      */
@@ -368,7 +368,7 @@
             int bufferSizeInBytes, int mode)
     throws IllegalArgumentException {
         this(streamType, sampleRateInHz, channelConfig, audioFormat,
-                bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE);
+                bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
     }
 
     /**
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 1fc236a..ed358d3 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -605,8 +605,9 @@
     // not only getting information from EXIF but also from some JPEG special segments such as
     // MARKER_COM for user comment and MARKER_SOFx for image width and height.
 
-    // Identifier for APP1 segment in JPEG
-    private static final byte[] IDENTIFIER_APP1 = "Exif\0\0".getBytes(Charset.forName("US-ASCII"));
+    // Identifier for EXIF APP1 segment in JPEG
+    private static final byte[] IDENTIFIER_EXIF_APP1 =
+            "Exif\0\0".getBytes(Charset.forName("US-ASCII"));
     // JPEG segment markers, that each marker consumes two bytes beginning with 0xff and ending with
     // the indicator. There is no SOF4, SOF8, SOF16 markers in JPEG and SOFx markers indicates start
     // of frame(baseline DCT) and the image size info exists in its beginning part.
@@ -1125,7 +1126,9 @@
         String time = getAttribute(TAG_GPS_TIMESTAMP);
         if (date == null || time == null
                 || (!sNonZeroTimePattern.matcher(date).matches()
-                && !sNonZeroTimePattern.matcher(time).matches())) return -1;
+                && !sNonZeroTimePattern.matcher(time).matches())) {
+            return -1;
+        }
 
         String dateTimeString = date + ' ' + time;
 
@@ -1176,7 +1179,6 @@
         DataInputStream dataInputStream = new DataInputStream(inputStream);
         byte marker;
         int bytesRead = 0;
-        ++bytesRead;
         if ((marker = dataInputStream.readByte()) != MARKER) {
             throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff));
         }
@@ -1184,8 +1186,8 @@
         if (dataInputStream.readByte() != MARKER_SOI) {
             throw new IOException("Invalid marker: " + Integer.toHexString(marker & 0xff));
         }
+        ++bytesRead;
         while (true) {
-            ++bytesRead;
             marker = dataInputStream.readByte();
             if (marker != MARKER) {
                 throw new IOException("Invalid marker:" + Integer.toHexString(marker & 0xff));
@@ -1195,36 +1197,40 @@
             if (DEBUG) {
                 Log.d(TAG, "Found JPEG segment indicator: " + Integer.toHexString(marker & 0xff));
             }
+            ++bytesRead;
 
             // EOI indicates the end of an image and in case of SOS, JPEG image stream starts and
             // the image data will terminate right after.
             if (marker == MARKER_EOI || marker == MARKER_SOS) {
                 break;
             }
-            bytesRead += 2;
             int length = dataInputStream.readUnsignedShort() - 2;
+            bytesRead += 2;
+            if (DEBUG) {
+                Log.d(TAG, "JPEG segment: " + marker + " (length: " + (length + 2) + ")");
+            }
             if (length < 0) {
                 throw new IOException("Invalid length");
             }
-            bytesRead += length;
             switch (marker) {
                 case MARKER_APP1: {
                     if (DEBUG) {
                         Log.d(TAG, "MARKER_APP1");
                     }
-                    bytesRead -= length;
                     if (length < 6) {
-                        throw new IOException("Invalid exif");
+                        // Skip if it's not an EXIF APP1 segment.
+                        break;
                     }
                     byte[] identifier = new byte[6];
                     if (inputStream.read(identifier) != 6) {
                         throw new IOException("Invalid exif");
                     }
-                    if (!Arrays.equals(identifier, IDENTIFIER_APP1)) {
-                        throw new IOException("Invalid app1 identifier");
-                    }
                     bytesRead += 6;
                     length -= 6;
+                    if (!Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) {
+                        // Skip if it's not an EXIF APP1 segment.
+                        break;
+                    }
                     if (length <= 0) {
                         throw new IOException("Invalid exif");
                     }
@@ -1246,6 +1252,7 @@
                     if (dataInputStream.read(bytes) != length) {
                         throw new IOException("Invalid exif");
                     }
+                    length = 0;
                     setAttribute("UserComment", new String(bytes, Charset.forName("US-ASCII")));
                     break;
                 }
@@ -1279,6 +1286,7 @@
                 throw new IOException("Invalid length");
             }
             dataInputStream.skipBytes(length);
+            bytesRead += length;
         }
     }
 
@@ -1292,68 +1300,84 @@
         }
         DataInputStream dataInputStream = new DataInputStream(inputStream);
         ExifDataOutputStream dataOutputStream = new ExifDataOutputStream(outputStream);
-        int bytesRead = 0;
-        ++bytesRead;
         if (dataInputStream.readByte() != MARKER) {
             throw new IOException("Invalid marker");
         }
         dataOutputStream.writeByte(MARKER);
-        ++bytesRead;
         if (dataInputStream.readByte() != MARKER_SOI) {
             throw new IOException("Invalid marker");
         }
         dataOutputStream.writeByte(MARKER_SOI);
 
+        // Write EXIF APP1 segment
+        dataOutputStream.writeByte(MARKER);
+        dataOutputStream.writeByte(MARKER_APP1);
+        writeExifSegment(dataOutputStream, 6);
+
         byte[] bytes = new byte[4096];
 
         while (true) {
-            ++bytesRead;
             if (dataInputStream.readByte() != MARKER) {
                 throw new IOException("Invalid marker");
             }
-            dataOutputStream.writeByte(MARKER);
-            ++bytesRead;
             byte marker = dataInputStream.readByte();
-            dataOutputStream.writeByte(marker);
             switch (marker) {
                 case MARKER_APP1: {
-                    // Rewrite EXIF segment
                     int length = dataInputStream.readUnsignedShort() - 2;
                     if (length < 0) {
                         throw new IOException("Invalid length");
                     }
-                    bytesRead += 2;
+                    byte[] identifier = new byte[6];
+                    if (length >= 6) {
+                        if (dataInputStream.read(identifier) != 6) {
+                            throw new IOException("Invalid exif");
+                        }
+                        if (Arrays.equals(identifier, IDENTIFIER_EXIF_APP1)) {
+                            // Skip the original EXIF APP1 segment.
+                            if (dataInputStream.skip(length - 6) != length - 6) {
+                                throw new IOException("Invalid length");
+                            }
+                            break;
+                        }
+                    }
+                    // Copy non-EXIF APP1 segment.
+                    dataOutputStream.writeUnsignedShort(length + 2);
+                    if (length >= 6) {
+                        length -= 6;
+                        dataOutputStream.write(identifier);
+                    }
                     int read;
-                    while ((read = dataInputStream.read(
-                            bytes, 0, Math.min(length, bytes.length))) > 0) {
+                    while (length > 0 && (read = dataInputStream.read(
+                            bytes, 0, Math.min(length, bytes.length))) >= 0) {
+                        dataOutputStream.write(bytes, 0, read);
                         length -= read;
                     }
-                    bytesRead += length;
-                    writeExifSegment(dataOutputStream, bytesRead);
                     break;
                 }
                 case MARKER_EOI:
                 case MARKER_SOS: {
+                    dataOutputStream.writeByte(MARKER);
+                    dataOutputStream.writeByte(marker);
                     // Copy all the remaining data
                     Streams.copy(dataInputStream, dataOutputStream);
                     return;
                 }
                 default: {
                     // Copy JPEG segment
+                    dataOutputStream.writeByte(MARKER);
+                    dataOutputStream.writeByte(marker);
                     int length = dataInputStream.readUnsignedShort();
                     dataOutputStream.writeUnsignedShort(length);
+                    length -= 2;
                     if (length < 0) {
                         throw new IOException("Invalid length");
                     }
-                    length -= 2;
-                    bytesRead += 2;
                     int read;
-                    while ((read = dataInputStream.read(
-                            bytes, 0, Math.min(length, bytes.length))) > 0) {
+                    while (length > 0 && (read = dataInputStream.read(
+                            bytes, 0, Math.min(length, bytes.length))) >= 0) {
                         dataOutputStream.write(bytes, 0, read);
                         length -= read;
                     }
-                    bytesRead += length;
                     break;
                 }
             }
@@ -1924,7 +1948,7 @@
 
         // Write TIFF Headers. See JEITA CP-3451C Table 1. page 10.
         dataOutputStream.writeUnsignedShort(totalSize);
-        dataOutputStream.write(IDENTIFIER_APP1);
+        dataOutputStream.write(IDENTIFIER_EXIF_APP1);
         dataOutputStream.writeShort(BYTE_ALIGN_MM);
         dataOutputStream.writeUnsignedShort(0x2a);
         dataOutputStream.writeUnsignedInt(8);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 26061e4..346f083 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -508,7 +508,8 @@
      * The associated value is an integer.
      * Constants are declared in {@link MediaCodecInfo.CodecProfileLevel}.
      * This key is used as a hint, and is only supported for codecs
-     * that specify a profile.
+     * that specify a profile. Note: Codecs are free to use all the available
+     * coding tools at the specified profile.
      *
      * @see MediaCodecInfo.CodecCapabilities#profileLevels
      */
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 56d3c99..adeb834 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -36,30 +36,28 @@
     private AudioMixingRule mRule;
     private AudioFormat mFormat;
     private int mRouteFlags;
-    private String mRegistrationId;
     private int mMixType = MIX_TYPE_INVALID;
 
     // written by AudioPolicy
     int mMixState = MIX_STATE_DISABLED;
     int mCallbackFlags;
+    String mDeviceAddress;
 
     // initialized in constructor, read by AudioPolicyConfig
-    final int mDeviceId;
-    final String mDeviceAddress;
+    final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
 
     /**
      * All parameters are guaranteed valid through the Builder.
      */
     private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
-            int deviceId, String deviceAddress) {
+            int deviceType, String deviceAddress) {
         mRule = rule;
         mFormat = format;
         mRouteFlags = routeFlags;
-        mRegistrationId = null;
         mMixType = rule.getTargetMixType();
         mCallbackFlags = callbackFlags;
-        mDeviceId = deviceId;
-        mDeviceAddress = deviceAddress;
+        mDeviceSystemType = deviceType;
+        mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress;
     }
 
     // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined
@@ -155,12 +153,12 @@
     }
 
     void setRegistration(String regId) {
-        mRegistrationId = regId;
+        mDeviceAddress = regId;
     }
 
     /** @hide */
     public String getRegistration() {
-        return mRegistrationId;
+        return mDeviceAddress;
     }
 
     /** @hide */
@@ -185,7 +183,8 @@
         private AudioFormat mFormat = null;
         private int mRouteFlags = 0;
         private int mCallbackFlags = 0;
-        private int mDeviceId = -1;
+        // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
+        private int mDeviceSystemType = AudioSystem.DEVICE_NONE;
         private String mDeviceAddress = null;
 
         /**
@@ -243,12 +242,12 @@
         /**
          * @hide
          * Only used by AudioPolicyConfig, not a public API.
-         * @param deviceId
+         * @param deviceType an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
          * @param address
          * @return the same Builder instance.
          */
-        Builder setDevice(int deviceId, String address) {
-            mDeviceId = deviceId;
+        Builder setDevice(int deviceType, String address) {
+            mDeviceSystemType = deviceType;
             mDeviceAddress = address;
             return this;
         }
@@ -312,7 +311,7 @@
             if (!device.isSink()) {
                 throw new IllegalArgumentException("Unsupported device type on mix, not a sink");
             }
-            mDeviceId = device.getId();
+            mDeviceSystemType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
             mDeviceAddress = device.getAddress();
             return this;
         }
@@ -344,7 +343,9 @@
                 }
                 mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
             }
-            if (mDeviceId != -1) {
+            if ((mDeviceSystemType != AudioSystem.DEVICE_NONE)
+                    && (mDeviceSystemType != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)
+                    && (mDeviceSystemType != AudioSystem.DEVICE_IN_REMOTE_SUBMIX)) {
                 if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) {
                     throw new IllegalArgumentException(
                             "Can't have audio device without flag ROUTE_FLAG_RENDER");
@@ -357,8 +358,17 @@
                     throw new IllegalArgumentException(
                             "Can't have flag ROUTE_FLAG_RENDER without an audio device");
                 }
+                if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) {
+                    if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) {
+                        mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                    } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) {
+                        mDeviceSystemType = AudioSystem.DEVICE_IN_REMOTE_SUBMIX;
+                    } else {
+                        throw new IllegalArgumentException("Unknown mixing rule type");
+                    }
+                }
             }
-            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId,
+            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType,
                     mDeviceAddress);
         }
     }
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 3af3ae7..cafa5a8 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -84,7 +84,7 @@
             // write callback flags
             dest.writeInt(mix.mCallbackFlags);
             // write device information
-            dest.writeInt(mix.mDeviceId);
+            dest.writeInt(mix.mDeviceSystemType);
             dest.writeString(mix.mDeviceAddress);
             // write mix format
             dest.writeInt(mix.getFormat().getSampleRate());
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 89e4577..3eb3359 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -302,7 +302,6 @@
      * Interface used to receive the created session.
      * @hide
      */
-    @SystemApi
     public abstract static class SessionCallback {
         /**
          * This is called after {@link TvInputManager#createSession} has been processed.
@@ -418,9 +417,7 @@
          * @param top Top position.
          * @param right Right position.
          * @param bottom Bottom position.
-         * @hide
          */
-        @SystemApi
         public void onLayoutSurface(Session session, int left, int top, int right, int bottom) {
         }
 
@@ -430,9 +427,7 @@
          * @param session A {@link TvInputManager.Session} associated with this callback
          * @param eventType The type of the event.
          * @param eventArgs Optional arguments of the event.
-         * @hide
          */
-        @SystemApi
         public void onSessionEvent(Session session, String eventType, Bundle eventArgs) {
         }
 
@@ -1347,7 +1342,6 @@
      * @param handler A {@link Handler} that the session creation will be delivered to.
      * @hide
      */
-    @SystemApi
     public void createSession(@NonNull String inputId, @NonNull final SessionCallback callback,
             @NonNull Handler handler) {
         createSessionInternal(inputId, false, callback, handler);
@@ -1364,7 +1358,6 @@
      * @param handler A {@link Handler} that the session creation will be delivered to.
      * @hide
      */
-    @SystemApi
     public void createRecordingSession(@NonNull String inputId,
             @NonNull final SessionCallback callback, @NonNull Handler handler) {
         createSessionInternal(inputId, true, callback, handler);
@@ -1544,7 +1537,6 @@
      * The Session provides the per-session functionality of TV inputs.
      * @hide
      */
-    @SystemApi
     public static final class Session {
         static final int DISPATCH_IN_PROGRESS = -1;
         static final int DISPATCH_NOT_HANDLED = 0;
@@ -1656,9 +1648,7 @@
          * @param format The new PixelFormat of the surface.
          * @param width The new width of the surface.
          * @param height The new height of the surface.
-         * @hide
          */
-        @SystemApi
         public void dispatchSurfaceChanged(int format, int width, int height) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
@@ -1706,9 +1696,7 @@
          *
          * @param channelUri The URI of a channel.
          * @param params A set of extra parameters which might be handled with this tune event.
-         * @hide
          */
-        @SystemApi
         public void tune(@NonNull Uri channelUri, Bundle params) {
             Preconditions.checkNotNull(channelUri);
             if (mToken == null) {
@@ -2065,9 +2053,7 @@
          *            i.e. prefixed with a package name you own, so that different developers will
          *            not create conflicting commands.
          * @param data Any data to include with the command.
-         * @hide
          */
-        @SystemApi
         public void sendAppPrivateCommand(String action, Bundle data) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index bc20c17..88be686 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -904,9 +904,7 @@
          *            i.e. prefixed with a package name you own, so that different developers will
          *            not create conflicting commands.
          * @param data Any data to include with the command.
-         * @hide
          */
-        @SystemApi
         public void onAppPrivateCommand(@NonNull String action, Bundle data) {
         }
 
@@ -1755,9 +1753,7 @@
          *            i.e. prefixed with a package name you own, so that different developers will
          *            not create conflicting commands.
          * @param data Any data to include with the command.
-         * @hide
          */
-        @SystemApi
         public void onAppPrivateCommand(@NonNull String action, Bundle data) {
         }
 
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index d48ea21e..da1002d 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -200,16 +200,14 @@
     }
 
     /**
-     * Calls {@link TvInputService.RecordingSession#appPrivateCommand(String, Bundle)} for the
-     * current recording session.
+     * Sends a private command to the underlying TV input. This can be used to provide
+     * domain-specific features that are only known between certain clients and their TV inputs.
      *
      * @param action The name of the private command to send. This <em>must</em> be a scoped name,
      *            i.e. prefixed with a package name you own, so that different developers will not
      *            create conflicting commands.
      * @param data An optional bundle to send with the command.
-     * @hide
      */
-    @SystemApi
     public void sendAppPrivateCommand(@NonNull String action, Bundle data) {
         if (TextUtils.isEmpty(action)) {
             throw new IllegalArgumentException("action cannot be null or an empty string");
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 9623076..6ca6193c 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -293,7 +293,7 @@
 
     /**
      * Tunes to a given channel. This can be used to provide domain-specific features that are only
-     * known between certain TvView applications and their TV inputs.
+     * known between certain clients and their TV inputs.
      *
      * @param inputId The ID of TV input for the given channel.
      * @param channelUri The URI of a channel.
@@ -550,16 +550,14 @@
     }
 
     /**
-     * Calls {@link TvInputService.Session#onAppPrivateCommand(String, Bundle)} for the current
-     * session.
+     * Sends a private command to the underlying TV input. This can be used to provide
+     * domain-specific features that are only known between certain clients and their TV inputs.
      *
      * @param action The name of the private command to send. This <em>must</em> be a scoped name,
      *            i.e. prefixed with a package name you own, so that different developers will not
      *            create conflicting commands.
      * @param data An optional bundle to send with the command.
-     * @hide
      */
-    @SystemApi
     public void sendAppPrivateCommand(@NonNull String action, Bundle data) {
         if (TextUtils.isEmpty(action)) {
             throw new IllegalArgumentException("action cannot be null or an empty string");
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index e9d62de..2fb1a3b 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -906,14 +906,16 @@
     android_media_MediaPlayer_release(env, thiz);
 }
 
-static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz, jint sessionId) {
+static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env,  jobject thiz,
+        jint sessionId) {
     ALOGV("set_session_id(): %d", sessionId);
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return;
     }
-    process_media_player_call( env, thiz, mp->setAudioSessionId(sessionId), NULL, NULL );
+    process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL,
+            NULL);
 }
 
 static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env,  jobject thiz) {
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index fa69135..10efe18 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -351,7 +351,7 @@
                                     priority,
                                     effectCallback,
                                     &lpJniStorage->mCallbackData,
-                                    sessionId,
+                                    (audio_session_t) sessionId,
                                     0);
     if (lpAudioEffect == 0) {
         ALOGE("Error creating AudioEffect");
@@ -819,7 +819,7 @@
     effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing];
     uint32_t numEffects = AudioEffect::kMaxPreProcessing;
 
-    status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
+    status_t status = AudioEffect::queryDefaultPreProcessing((audio_session_t) audioSession,
                                            descriptors,
                                            &numEffects);
     if (status != NO_ERROR || numEffects == 0) {
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 3d3adba..f1a8c6f 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -388,7 +388,7 @@
                                   0,
                                   android_media_visualizer_effect_callback,
                                   lpJniStorage,
-                                  sessionId);
+                                  (audio_session_t) sessionId);
     if (lpVisualizer == 0) {
         ALOGE("Error creating Visualizer");
         goto setup_failure;
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 76c701a..5cfe300 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -105,6 +105,14 @@
 
 /*****************************************************************************/
 
+int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor,
+        int32_t samplingPeriodUs, int maxBatchReportLatencyUs)
+{
+    return static_cast<SensorEventQueue*>(queue)->enableSensor(
+            static_cast<Sensor const*>(sensor)->getHandle(), samplingPeriodUs,
+                    maxBatchReportLatencyUs, 0);
+}
+
 int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor)
 {
     return static_cast<SensorEventQueue*>(queue)->enableSensor(
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index ccf1501..55d000c 100644
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -13,8 +13,8 @@
 
     <application android:label="@string/service_name"
                  android:allowBackup="false"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
 
         <service android:name=".DefaultContainerService"
                  android:enabled="true"
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 6fe239e..a4acf7e 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -107,7 +107,7 @@
             </intent-filter>
         </receiver>
 
-        <receiver android:name=".BootReceiver">
+        <receiver android:name=".BootReceiver" android:enabled="false">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
diff --git a/packages/DocumentsUI/app-perf-tests/Android.mk b/packages/DocumentsUI/app-perf-tests/Android.mk
new file mode 100644
index 0000000..3f12906
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIAppPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
new file mode 100644
index 0000000..1c3ed80
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.documentsui.appperftests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name="com.android.documentsui.LauncherActivity" />
+    </application>
+
+    <!-- This package instrumentates itself, so the DocumentsUI process can be killed without
+         killing the testing package. -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.documentsui.appperftests"
+        android:label="App performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
new file mode 100644
index 0000000..d6e8a96
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.documentsui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.test.uiautomator.UiDevice;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesAppPerfTest extends InstrumentationTestCase {
+
+    // Keys used to report metrics to APCT.
+    private static final String KEY_FILES_COLD_START_PERFORMANCE_MEDIAN =
+            "files-cold-start-performance-median";
+    private static final String KEY_FILES_WARM_START_PERFORMANCE_MEDIAN =
+            "files-warm-start-performance-median";
+
+    private static final String TARGET_PACKAGE = "com.android.documentsui";
+
+    private static final int NUM_MEASUREMENTS = 10;
+
+    private LauncherActivity mActivity;
+    private UiDevice mDevice;
+
+    @Override
+    public void setUp() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+    }
+
+    public void testFilesColdStartPerformance() throws Exception {
+        runFilesStartPerformanceTest(true);
+    }
+
+    public void testFilesWarmStartPerformance() throws Exception {
+        runFilesStartPerformanceTest(false);
+    }
+
+    public void runFilesStartPerformanceTest(boolean cold) throws Exception {
+        long[] measurements = new long[NUM_MEASUREMENTS];
+        for (int i = 0; i < NUM_MEASUREMENTS; i++) {
+            if (cold) {
+                // Kill all providers, as well as DocumentsUI to measure a cold start.
+                killProviders();
+                mDevice.executeShellCommand("am force-stop " + TARGET_PACKAGE);
+            }
+            mDevice.waitForIdle();
+
+            LauncherActivity.testCaseLatch = new CountDownLatch(1);
+            mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+                    LauncherActivity.class, null);
+            LauncherActivity.testCaseLatch.await();
+            measurements[i] = LauncherActivity.measurement;
+        }
+
+        reportMetrics(cold ? KEY_FILES_COLD_START_PERFORMANCE_MEDIAN
+                : KEY_FILES_WARM_START_PERFORMANCE_MEDIAN, measurements);
+    }
+
+    private void reportMetrics(String key, long[] measurements) {
+        final Bundle status = new Bundle();
+        Arrays.sort(measurements);
+        final long median = measurements[NUM_MEASUREMENTS / 2 - 1];
+        status.putDouble(key, median);
+
+        getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+    }
+
+    private void killProviders() throws Exception {
+        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+        final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
+        for (ResolveInfo info : providers) {
+            final String packageName = info.providerInfo.packageName;
+            mDevice.executeShellCommand("am force-stop " + packageName);
+        }
+    }
+}
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
new file mode 100644
index 0000000..21fc52e
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
@@ -0,0 +1,64 @@
+/*
+ * 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.documentsui;
+
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+
+public class LauncherActivity extends Activity {
+    private static final String TARGET_PACKAGE = "com.android.documentsui";
+    private static final int BENCHMARK_REQUEST_CODE = 1986;
+
+    public static CountDownLatch testCaseLatch = null;
+    public static long measurement = -1;
+
+    private long mStartTime = -1;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        new Handler().post(new Runnable() {
+            @Override public void run() {
+                final Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT");
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
+                intent.putExtra(EXTRA_BENCHMARK, true);
+                intent.setType("*/*");
+
+                mStartTime = System.currentTimeMillis();
+                startActivityForResult(intent, BENCHMARK_REQUEST_CODE);
+            }
+        });
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == BENCHMARK_REQUEST_CODE) {
+            measurement = System.currentTimeMillis() - mStartTime;
+            testCaseLatch.countDown();
+            finish();
+        }
+    }
+}
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index 86087c3..ebb3969 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -21,4 +21,8 @@
     <!-- Intentionally unset. Vendors should set this in an overlay. -->
     <string name="trusted_quick_viewer_package" translatable="false"></string>
     <bool name="list_divider_inset_left">true</bool>
+    <!-- Indicates if the home directory should be hidden in the roots list, that is presented
+         in the drawer/left side panel ) -->
+    <bool name="home_root_hidden">true</bool>
+
 </resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index e7406e68..0d098e6 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -211,13 +211,29 @@
     <!-- Text in the button asking user to deny access to a given directory. -->
     <string name="deny">Deny</string>
     <!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
-    <plurals name="delete_confirmation_message">
-        <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
-        <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
-    </plurals>
     <!-- Label text showing user how many items are selected. Can be one or more elements. -->
     <plurals name="elements_selected">
         <item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> selected</item>
         <item quantity="other"><xliff:g id="count" example="3">%1$d</xliff:g> selected</item>
     </plurals>
+
+    <!-- Dialog text shown to users when asking if they want to delete a file (a confirmation) -->
+    <string name="delete_filename_confirmation_message">Delete \"<xliff:g id="name" example="cat.jpg">%1$s</xliff:g>\"?</string>
+    <!-- Dialog text shown to users when asking if they want to delete a folder (a confirmation) -->
+    <string name="delete_foldername_confirmation_message">Delete folder \"<xliff:g id="name" example="Photos">%1$s</xliff:g>\" and its contents?</string>
+    <!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
+    <plurals name="delete_files_confirmation_message">
+        <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
+        <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
+    </plurals>
+    <!-- Dialog text shown to users when asking if they want to delete folders (a confirmation). -->
+    <plurals name="delete_folders_confirmation_message">
+        <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> folder and its contents?</item>
+        <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> folders and their contents?</item>
+    </plurals>
+    <!-- Dialog text shown to users when asking if they want to delete mixed type items: files and folders (a confirmation). -->
+    <plurals name="delete_items_confirmation_message">
+        <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> item?</item>
+        <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> items?</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index c51cbb3..fe61094 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -17,6 +17,7 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
 import static com.android.documentsui.State.MODE_GRID;
 
 import android.app.Activity;
@@ -30,6 +31,9 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.MessageQueue;
+import android.os.MessageQueue.IdleHandler;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.support.annotation.CallSuper;
@@ -60,6 +64,8 @@
 public abstract class BaseActivity extends Activity
         implements SearchManagerListener, NavigationView.Environment {
 
+    private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests";
+
     State mState;
     RootsCache mRoots;
     SearchViewManager mSearchManager;
@@ -92,11 +98,20 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        final Intent intent = getIntent();
+
+        // If startup benchmark is requested by a whitelisted testing package, then close the
+        // activity once idle, and notify the testing activity.
+        if (intent.getBooleanExtra(EXTRA_BENCHMARK, false) &&
+                BENCHMARK_TESTING_PACKAGE.equals(getCallingPackage())) {
+            closeOnIdleForTesting();
+        }
+
         setContentView(mLayoutId);
 
         mDrawer = DrawerController.create(this);
         mState = getState(icicle);
-        Metrics.logActivityLaunch(this, mState, getIntent());
+        Metrics.logActivityLaunch(this, mState, intent);
 
         mRoots = DocumentsApplication.getRootsCache(this);
 
@@ -668,6 +683,33 @@
         }
     }
 
+    /**
+     * Closes the activity when it's idle. Used only for tests.
+     */
+    private void closeOnIdleForTesting() {
+        addEventListener(new EventListener() {
+            @Override
+            public void onDirectoryNavigated(Uri uri) {
+            }
+
+            @Override
+            public void onDirectoryLoaded(Uri uri) {
+                getMainLooper().getQueue().addIdleHandler(new IdleHandler() {
+                    @Override
+                    public boolean queueIdle() {
+                        setResult(RESULT_OK);
+                        finish();
+                        return false;
+                    }
+                });
+                new Handler().post(new Runnable() {
+                    @Override public void run() {
+                    }
+                });
+            }
+        });
+    }
+
     private static final class HandleRootsChangedTask
             extends PairedTask<BaseActivity, RootInfo, RootInfo> {
         DocumentInfo mDownloadsDocument;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 9f83c04..54e6287 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -317,7 +317,10 @@
 
             for (final RootInfo root : roots) {
                 final RootItem item = new RootItem(root);
-                if (root.isLibrary()) {
+
+                if (root.isHome() && isHomeRootHidden(context)) {
+                    continue;
+                } else if (root.isLibrary()) {
                     if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
                     libraries.add(item);
                 } else {
@@ -367,6 +370,13 @@
             }
         }
 
+        /*
+         * Indicates if the home directory should be hidden in the roots list.
+         */
+        private boolean isHomeRootHidden(Context context) {
+            return context.getResources().getBoolean(R.bool.home_root_hidden);
+        }
+
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             final Item item = getItem(position);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index b539421..6f1863e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -86,6 +86,11 @@
      */
     public static final String EXTRA_IGNORE_STATE = "ignoreState";
 
+    /**
+     * Extra for an Intent for enabling performance benchmark. Used only by tests.
+     */
+    public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark";
+
     private static final Collator sCollator;
 
     static {
@@ -133,8 +138,7 @@
 
     /**
      * Compare two strings against each other using system default collator in a
-     * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX}
-     * before other items.
+     * case-insensitive mode.
      */
     public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
         final boolean leftEmpty = TextUtils.isEmpty(lhs);
@@ -147,6 +151,14 @@
         return sCollator.compare(lhs, rhs);
     }
 
+    /**
+     * Compare two strings against each other using system default collator in a
+     * case-insensitive mode.
+     */
+    public static int compareToIgnoreCase(String lhs, String rhs) {
+        return sCollator.compare(lhs, rhs);
+    }
+
     public static boolean isHardwareKeyboardAvailable(Context context) {
         return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index be70417..60e4b9a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -98,7 +98,6 @@
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
 import com.android.documentsui.services.FileOperations;
-
 import com.google.common.collect.Lists;
 
 import java.lang.annotation.Retention;
@@ -165,6 +164,7 @@
     private String mQuery = null;
     private Selection mSelection = null;
     private boolean mSearchMode = false;
+    private @Nullable ActionMode mActionMode;
 
     @Override
     public View onCreateView(
@@ -406,9 +406,9 @@
         int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
         int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
 
-        assert(mRecView.getWidth() > 0);
-
-        int columnCount = Math.max(1,
+        // RecyclerView sometimes gets a width of 0 (see b/27150284).  Clamp so that we always lay
+        // out the grid with at least 2 columns.
+        int columnCount = Math.max(2,
                 (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
 
         return columnCount;
@@ -439,7 +439,6 @@
             implements MultiSelectManager.Callback, ActionMode.Callback {
 
         private Selection mSelected = new Selection();
-        private ActionMode mActionMode;
         private int mNoCopyCount = 0;
         private int mNoDeleteCount = 0;
         private int mNoRenameCount = -1;
@@ -578,10 +577,9 @@
                     return true;
 
                 case R.id.menu_delete:
-                    // Pass mode along to the delete function so it can
-                    // end action mode when documents are deleted.
+                    // deleteDocuments will end action mode if the documents are deleted.
                     // It won't end action mode if user cancels the delete.
-                    deleteDocuments(selection, mode);
+                    deleteDocuments(selection);
                     return true;
 
                 case R.id.menu_copy_to:
@@ -690,7 +688,40 @@
         }.execute(selected);
     }
 
-    private void deleteDocuments(final Selection selected, final ActionMode mode) {
+    private String generateDeleteMessage(final List<DocumentInfo> docs) {
+        String message;
+        int dirsCount = 0;
+
+        for (DocumentInfo doc : docs) {
+            if (doc.isDirectory()) {
+                ++dirsCount;
+            }
+        }
+
+        if (docs.size() == 1) {
+            // Deleteing 1 file xor 1 folder in cwd
+            message = dirsCount == 0
+                    ? getActivity().getString(R.string.delete_filename_confirmation_message,
+                            docs.get(0).displayName)
+                    : getActivity().getString(R.string.delete_foldername_confirmation_message,
+                            docs.get(0).displayName);
+        } else if (dirsCount == 0) {
+            // Deleting only files in cwd
+            message = Shared.getQuantityString(getActivity(),
+                    R.plurals.delete_files_confirmation_message, docs.size());
+        } else if (dirsCount == docs.size()) {
+            // Deleting only folders in cwd
+            message = Shared.getQuantityString(getActivity(),
+                    R.plurals.delete_folders_confirmation_message, docs.size());
+        } else {
+            // Deleting mixed items (files and folders) in cwd
+            message = Shared.getQuantityString(getActivity(),
+                    R.plurals.delete_items_confirmation_message, docs.size());
+        }
+        return message;
+    }
+
+    private void deleteDocuments(final Selection selected) {
         assert(!selected.isEmpty());
 
         final DocumentInfo srcParent = getDisplayState().stack.peek();
@@ -700,11 +731,7 @@
 
                 TextView message =
                         (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null);
-                message.setText(
-                        Shared.getQuantityString(
-                                getActivity(),
-                                R.plurals.delete_confirmation_message,
-                                docs.size()));
+                message.setText(generateDeleteMessage(docs));
 
                 // This "insta-hides" files that are being deleted, because
                 // the delete operation may be not execute immediately (it
@@ -727,7 +754,9 @@
                                 // This is done here, rather in the onActionItemClicked
                                 // so we can avoid de-selecting items in the case where
                                 // the user cancels the delete.
-                                mode.finish();
+                                if (mActionMode != null) {
+                                    mActionMode.finish();
+                                }
                                 // Hide the files in the UI...since the operation
                                 // might be queued up on FileOperationService.
                                 // We're walking a line here.
@@ -1263,12 +1292,25 @@
             }
 
             // Handle enter key events
-            if (keyCode == KeyEvent.KEYCODE_ENTER) {
-                if (event.isShiftPressed()) {
-                    return onSelect(doc);
-                } else {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_ENTER:
+                    if (event.isShiftPressed()) {
+                        return onSelect(doc);
+                    }
+                    // For non-shifted enter keypresses, fall through.
+                case KeyEvent.KEYCODE_DPAD_CENTER:
+                case KeyEvent.KEYCODE_BUTTON_A:
                     return onActivate(doc);
-                }
+                case KeyEvent.KEYCODE_FORWARD_DEL:
+                    // This has to be handled here instead of in a keyboard shortcut, because
+                    // keyboard shortcuts all have to be modified with the 'Ctrl' key.
+                    if (mSelectionManager.hasSelection()) {
+                        deleteDocuments(mSelectionManager.getSelection());
+                    }
+                    // Always handle the key, even if there was nothing to delete. This is a
+                    // precaution to prevent other handlers from potentially picking up the event
+                    // and triggering extra behaviours.
+                    return true;
             }
 
             return false;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 5edda38..450341f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -77,10 +77,18 @@
     /**
      * Makes the associated item view appear selected. Note that this merely affects the appearance
      * of the view, it doesn't actually select the item.
+     * TODO: Use the DirectoryItemAnimator instead of manually controlling animation using a boolean
+     * flag.
      *
      * @param selected
+     * @param animate Whether or not to animate the change. Only selection changes initiated by the
+     *            selection manager should be animated. See
+     *            {@link ModelBackedDocumentsAdapter#onBindViewHolder(DocumentHolder, int, java.util.List)}
      */
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
+        // Note: the animate param doesn't apply for this base implementation, because the
+        // DirectoryItemAnimator takes care of it. It's required by subclasses, which perform their
+        // own animation.
         itemView.setActivated(selected);
         itemView.setBackgroundColor(selected ? mSelectedBgColor : mDefaultBgColor);
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index 39fdf8e..ea1deb4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -104,7 +104,8 @@
                 return false;
             }
 
-            if (mState.action == ACTION_OPEN_TREE) {
+            if (mState.action == ACTION_OPEN_TREE
+                    || mState.action == ACTION_PICK_COPY_DESTINATION) {
                 // In this case nothing *ever* is selectable...the expected user behavior is
                 // they navigate *into* a folder, then click a confirmation button indicating
                 // that the current directory is the directory they are picking.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index 90b2341..ce5bcb1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -42,12 +42,17 @@
     }
 
     @Override
-    public void setSelected(boolean selected) {
-        super.setSelected(selected);
+    public void setSelected(boolean selected, boolean animate) {
+        super.setSelected(selected, animate);
         float checkAlpha = selected ? 1f : 0f;
 
-        mIconCheck.animate().alpha(checkAlpha).start();
-        mIconMime.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+            mIconMime.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+            mIconMime.setAlpha(1f - checkAlpha);
+        }
     }
 
     /**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index c8641a8..c4f6f11 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -69,12 +69,16 @@
     }
 
     @Override
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
         // We always want to make sure our check box disappears if we're not selected,
         // even if the item is disabled. This is because this object can be reused
         // and this method will be called to setup initial state.
         float checkAlpha = selected ? 1f : 0f;
-        mIconCheck.animate().alpha(checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+        }
 
         // But it should be an error to be set to selected && be disabled.
         if (!itemView.isEnabled()) {
@@ -82,9 +86,13 @@
             return;
         }
 
-        super.setSelected(selected);
+        super.setSelected(selected, animate);
 
-        mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconMimeSm.setAlpha(1f - checkAlpha);
+        }
     }
 
     public void setEnabled(boolean enabled) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 3a1be11..ace53e0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -65,22 +65,31 @@
     }
 
     @Override
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
         // We always want to make sure our check box disappears if we're not selected,
         // even if the item is disabled. But it should be an error (see assert below)
         // to be set to selected && be disabled.
         float checkAlpha = selected ? 1f : 0f;
-        mIconCheck.animate().alpha(checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+        }
 
         if (!itemView.isEnabled()) {
             assert(!selected);
             return;
         }
 
-        super.setSelected(selected);
+        super.setSelected(selected, animate);
 
-        mIconMime.animate().alpha(1f - checkAlpha).start();
-        mIconThumb.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconMime.animate().alpha(1f - checkAlpha).start();
+            mIconThumb.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconMime.setAlpha(1f - checkAlpha);
+            mIconThumb.setAlpha(1f - checkAlpha);
+        }
     }
 
     @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 68b1bcc..3642b01 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -47,6 +47,7 @@
 @VisibleForTesting
 public class Model {
     private static final String TAG = "Model";
+    private static final String EMPTY = "";
 
     private boolean mIsLoading;
     private List<UpdateListener> mUpdateListeners = new ArrayList<>();
@@ -65,7 +66,7 @@
     private int mDocIdIndex = -1;
     private int mMimeTypeIndex = -1;
     private int mDisplayNameIndex = -1;
-    private int mColumnSizeIndex = -1;
+    private int mSizeIndex = -1;
     private int mLastModifiedIndex = -1;
 
     @Nullable String info;
@@ -114,7 +115,8 @@
         mDocIdIndex = mCursor.getColumnIndex(Document.COLUMN_DOCUMENT_ID);
         mMimeTypeIndex = mCursor.getColumnIndex(Document.COLUMN_MIME_TYPE);
         mDisplayNameIndex = mCursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME);
-        mColumnSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
+        mLastModifiedIndex = mCursor.getColumnIndex(Document.COLUMN_LAST_MODIFIED);
+        mSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE);
 
         doc = result.doc;
 
@@ -168,24 +170,23 @@
             // If the cursor is a merged cursor over multiple authorities, then prefix the ids
             // with the authority to avoid collisions.
             if (mCursor instanceof MergeCursor) {
-                mIds[pos] = getString(mAuthorityIndex) + "|" + mCursor.getString(mDocIdIndex);
+                mIds[pos] = getStringOrEmpty(mAuthorityIndex) + "|" + getStringOrEmpty(mDocIdIndex);
             } else {
-                mIds[pos] = mCursor.getString(mDocIdIndex);
+                mIds[pos] = getStringOrEmpty(mDocIdIndex);
             }
 
-            mimeType = getString(mMimeTypeIndex);
+            mimeType = getStringOrEmpty(mMimeTypeIndex);
             isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
 
             switch (mSortOrder) {
                 case SORT_ORDER_DISPLAY_NAME:
-                    displayNames[pos] = getString(mDisplayNameIndex);
+                    displayNames[pos] = getStringOrEmpty(mDisplayNameIndex);
                     break;
                 case SORT_ORDER_LAST_MODIFIED:
                     longValues[pos] = getLastModified();
                     break;
                 case SORT_ORDER_SIZE:
-                    longValues[pos] = mColumnSizeIndex != -1
-                            ? mCursor.getLong(mColumnSizeIndex) : 0;
+                    longValues[pos] = getDocSize();
                     break;
             }
         }
@@ -241,7 +242,7 @@
                 } else {
                     final String lhs = pivotValue;
                     final String rhs = sortKey[mid];
-                    compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+                    compare = Shared.compareToIgnoreCase(lhs, rhs);
                 }
 
                 if (compare < 0) {
@@ -361,18 +362,43 @@
         }
     }
 
-    private String getString(int columnIndex) {
-        return columnIndex != -1 ? mCursor.getString(columnIndex) : null;
+    /**
+     * @return Value of the string column, or an empty string if no value, or empty value.
+     */
+    private String getStringOrEmpty(int columnIndex) {
+        if (columnIndex == -1)
+            return EMPTY;
+        final String result = mCursor.getString(columnIndex);
+        return result != null ? result : EMPTY;
     }
 
     /**
      * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
-     * timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top
-     * when sorting by date.
+     * or missing timestamp - these will be replaced with MAX_LONG so that such files get sorted to
+     * the top when sorting by date.
      */
     private long getLastModified() {
-        long l = mCursor.getLong(mLastModifiedIndex);
-        return (l == -1) ? Long.MAX_VALUE : l;
+        if (mLastModifiedIndex == -1)
+            return Long.MAX_VALUE;
+        try {
+            final long result = mCursor.getLong(mLastModifiedIndex);
+            return result > 0 ? result : Long.MAX_VALUE;
+        } catch (NumberFormatException e) {
+            return Long.MAX_VALUE;
+        }
+    }
+
+    /**
+     * @return Size for the given document. If the size is unknown or invalid, returns 0.
+     */
+    private long getDocSize() {
+        if (mSizeIndex == -1)
+            return 0;
+        try {
+            return mCursor.getLong(mSizeIndex);
+        } catch (NumberFormatException e) {
+            return 0;
+        }
     }
 
     public @Nullable Cursor getItem(String modelId) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 149ecdd..ca3b2e2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -29,7 +29,6 @@
 import android.view.ViewGroup;
 
 import com.android.documentsui.State;
-
 import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
@@ -103,7 +102,7 @@
     public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
         if (payload.contains(SELECTION_CHANGED_MARKER)) {
             final boolean selected = mEnv.isSelected(mModelIds.get(position));
-            holder.setSelected(selected);
+            holder.setSelected(selected, true);
         } else {
             onBindViewHolder(holder, position);
         }
@@ -124,7 +123,7 @@
             assert(!selected);
         }
         holder.setEnabled(enabled);
-        holder.setSelected(mEnv.isSelected(modelId));
+        holder.setSelected(mEnv.isSelected(modelId), false);
 
         mEnv.onBindDocumentHolder(holder, cursor);
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index b0cc09a..b80486d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -903,7 +903,7 @@
             public Selection createFromParcel(Parcel in, ClassLoader loader) {
                 return new Selection(
                         in.readString(),
-                        (ArrayList<String>) in.readArrayList(loader));
+                        in.readArrayList(loader));
             }
 
             @Override
@@ -931,7 +931,6 @@
         Rect getAbsoluteRectForChildViewAt(int index);
         int getAdapterPositionAt(int index);
         int getColumnCount();
-        int getRowCount();
         int getChildCount();
         int getVisibleChildCount();
         /**
@@ -1008,13 +1007,6 @@
         }
 
         @Override
-        public int getRowCount() {
-            int numFullColumns = getChildCount() / getColumnCount();
-            boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0;
-            return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
-        }
-
-        @Override
         public int getHeight() {
             return mView.getHeight();
         }
@@ -1202,6 +1194,7 @@
             }
 
             mCurrentPosition = input.getOrigin();
+            mModel.resizeSelection(input.getOrigin());
             scrollViewIfNecessary();
             resizeBandSelectRectangle();
         }
@@ -1549,11 +1542,7 @@
                         mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right));
             }
 
-            if (mRowBounds.size() != mHelper.getRowCount()) {
-                // If not all y-limits have been recorded, record this one.
-                recordLimits(
-                        mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
-            }
+            recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
 
             SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
             if (columnList == null) {
@@ -1747,6 +1736,11 @@
                 return ((Limits) other).lowerLimit == lowerLimit &&
                         ((Limits) other).upperLimit == upperLimit;
             }
+
+            @Override
+            public String toString() {
+                return "(" + lowerLimit + ", " + upperLimit + ")";
+            }
         }
 
         /**
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index e4afc3d..f294919 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -58,18 +58,23 @@
     public void testRootsListed() throws Exception {
         initTestFiles();
 
-        bots.roots.openRoot(ROOT_0_ID);
-
         // Should also have Drive, but that requires pre-configuration of devices
         // We omit for now.
-        bots.roots.assertHasRoots(
+        bots.roots.assertRootsPresent(
                 "Images",
                 "Videos",
                 "Audio",
                 "Downloads",
-                "Documents",
                 ROOT_0_ID,
                 ROOT_1_ID);
+
+        // Separate logic for "Documents" root, which presence depends on the config setting
+        boolean homeRootHidden = context.getResources().getBoolean(R.bool.home_root_hidden);
+        if (homeRootHidden) {
+            bots.roots.assertRootsAbsent("Documents");
+        } else {
+            bots.roots.assertRootsPresent("Documents");
+        }
     }
 
     public void testFilesListed() throws Exception {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
index 356fd01..096af10 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
@@ -69,7 +69,7 @@
         mDevice.waitForIdle();
     }
 
-    public void assertHasRoots(String... labels) throws UiObjectNotFoundException {
+    public void assertRootsPresent(String... labels) throws UiObjectNotFoundException {
         List<String> missing = new ArrayList<>();
         for (String label : labels) {
             if (!findRoot(label).exists()) {
@@ -82,6 +82,18 @@
         }
     }
 
+    public void assertRootsAbsent(String... labels) throws UiObjectNotFoundException {
+        List<String> unexpected = new ArrayList<>();
+        for (String label : labels) {
+            if (findRoot(label).exists()) {
+                unexpected.add(label);
+            }
+        }
+        if (!unexpected.isEmpty()) {
+            Assert.fail("Unexpected roots " + unexpected);
+        }
+    }
+
     public void assertHasFocus() {
         assertHasFocus(ROOTS_LIST_ID);
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
index 353d4bd..0c0e0b7 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
@@ -27,6 +27,7 @@
 import com.android.documentsui.dirlist.MultiSelectManager.GridModel;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
 @SmallTest
@@ -42,6 +43,17 @@
     private Set<String> lastSelection;
     private int viewWidth;
 
+    // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and
+    // #resizeSelection methods instead.
+    //
+    // The reason for this is that selection is stateful and involves operations that take the
+    // current UI state (e.g scrolling) into account. This test maintains its own copy of the
+    // selection bounds as control data for verifying selections. Keep this data in sync by calling
+    // #startSelection and
+    // #resizeSelection.
+    private Point mSelectionOrigin;
+    private Point mSelectionPoint;
+
     private void initData(final int numChildren, int numColumns) {
         env = new TestEnvironment(numChildren, numColumns);
         adapter = new TestDocumentsAdapter(new ArrayList<String>()) {
@@ -76,139 +88,241 @@
 
     public void testSelectionLeftOfItems() {
         initData(20, 5);
-        model.startSelection(new Point(0, 10));
-        model.resizeSelection(new Point(1, 11));
-        assertSelected();
+        startSelection(new Point(0, 10));
+        resizeSelection(new Point(1, 11));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionRightOfItems() {
         initData(20, 4);
-        model.startSelection(new Point(viewWidth - 1, 10));
-        model.resizeSelection(new Point(viewWidth - 2, 11));
-        assertSelected();
+        startSelection(new Point(viewWidth - 1, 10));
+        resizeSelection(new Point(viewWidth - 2, 11));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionAboveItems() {
         initData(20, 4);
-        model.startSelection(new Point(10, 0));
-        model.resizeSelection(new Point(11, 1));
-        assertSelected();
+        startSelection(new Point(10, 0));
+        resizeSelection(new Point(11, 1));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionBelowItems() {
         initData(5, 4);
-        model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
-        model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
-        assertSelected();
+        startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+        resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testVerticalSelectionBetweenItems() {
         initData(20, 4);
-        model.startSelection(new Point(106, 0));
-        model.resizeSelection(new Point(107, 200));
-        assertSelected();
+        startSelection(new Point(106, 0));
+        resizeSelection(new Point(107, 200));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testHorizontalSelectionBetweenItems() {
         initData(20, 4);
-        model.startSelection(new Point(0, 105));
-        model.resizeSelection(new Point(200, 106));
-        assertSelected();
+        startSelection(new Point(0, 105));
+        resizeSelection(new Point(200, 106));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testGrowingAndShrinkingSelection() {
         initData(20, 4);
-        model.startSelection(new Point(0, 0));
-        model.resizeSelection(new Point(5, 5));
-        assertSelected(0);
-        model.resizeSelection(new Point(109, 109));
-        assertSelected(0);
-        model.resizeSelection(new Point(110, 109));
-        assertSelected(0, 1);
-        model.resizeSelection(new Point(110, 110));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(214, 214));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(215, 214));
-        assertSelected(0, 1, 2, 4, 5, 6);
-        model.resizeSelection(new Point(214, 214));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(110, 110));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(110, 109));
-        assertSelected(0, 1);
-        model.resizeSelection(new Point(109, 109));
-        assertSelected(0);
-        model.resizeSelection(new Point(5, 5));
-        assertSelected(0);
-        model.resizeSelection(new Point(0, 0));
-        assertSelected();
+        startSelection(new Point(0, 0));
+
+        resizeSelection(new Point(5, 5));
+        verifySelection();
+
+        resizeSelection(new Point(109, 109));
+        verifySelection();
+
+        resizeSelection(new Point(110, 109));
+        verifySelection();
+
+        resizeSelection(new Point(110, 110));
+        verifySelection();
+
+        resizeSelection(new Point(214, 214));
+        verifySelection();
+
+        resizeSelection(new Point(215, 214));
+        verifySelection();
+
+        resizeSelection(new Point(214, 214));
+        verifySelection();
+
+        resizeSelection(new Point(110, 110));
+        verifySelection();
+
+        resizeSelection(new Point(110, 109));
+        verifySelection();
+
+        resizeSelection(new Point(109, 109));
+        verifySelection();
+
+        resizeSelection(new Point(5, 5));
+        verifySelection();
+
+        resizeSelection(new Point(0, 0));
+        verifySelection();
+
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionMovingAroundOrigin() {
         initData(16, 4);
-        model.startSelection(new Point(210, 210));
-        model.resizeSelection(new Point(viewWidth - 1, 0));
-        assertSelected(2, 3, 6, 7);
-        model.resizeSelection(new Point(0, 0));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(0, 420));
-        assertSelected(8, 9, 12, 13);
-        model.resizeSelection(new Point(viewWidth - 1, 420));
-        assertSelected(10, 11, 14, 15);
-        assertEquals(10, model.getPositionNearestOrigin());
+
+        startSelection(new Point(210, 210));
+        resizeSelection(new Point(viewWidth - 1, 0));
+        verifySelection();
+
+        resizeSelection(new Point(0, 0));
+        verifySelection();
+
+        resizeSelection(new Point(0, 420));
+        verifySelection();
+
+        resizeSelection(new Point(viewWidth - 1, 420));
+        verifySelection();
+
+        // This is manually figured and will need to be adjusted if the separator position is
+        // changed.
+        assertEquals(7, model.getPositionNearestOrigin());
     }
 
     public void testScrollingBandSelect() {
         initData(40, 4);
-        model.startSelection(new Point(0, 0));
-        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 4, 8, 12, 16);
+
+        startSelection(new Point(0, 0));
+        resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         scroll(CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 4, 8, 12, 16, 20);
-        model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21);
+        verifySelection();
+
+        resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         scroll(CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25);
+        verifySelection();
+
         scroll(-2 * CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17);
-        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 4, 8, 12, 16);
+        verifySelection();
+
+        resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         assertEquals(0, model.getPositionNearestOrigin());
     }
 
-    private void assertSelected(int... selectedPositions) {
-        assertEquals(selectedPositions.length, lastSelection.size());
-        for (int position : selectedPositions) {
-            assertTrue(lastSelection.contains(Integer.toString(position)));
+    /** Returns the current selection area as a Rect. */
+    private Rect getSelectionArea() {
+        // Construct a rect from the two selection points.
+        Rect selectionArea = new Rect(
+                mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y);
+        selectionArea.union(mSelectionPoint.x, mSelectionPoint.y);
+        // Rect intersection tests are exclusive of bounds, while the MSM's selection code is
+        // inclusive. Expand the rect by 1 pixel in all directions to account for this.
+        selectionArea.inset(-1, -1);
+
+        return selectionArea;
+    }
+
+    /** Asserts that the selection is currently empty. */
+    private void assertNoSelection() {
+        assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(),
+                0, lastSelection.size());
+    }
+
+    /** Verifies the selection using actual bbox checks. */
+    private void verifySelection() {
+        Rect selectionArea = getSelectionArea();
+        for (TestEnvironment.Item item: env.items) {
+            if (Rect.intersects(selectionArea, item.rect)) {
+                assertTrue("Expected item " + item + " was not in selection " + selectionArea,
+                        lastSelection.contains(item.name));
+            } else {
+                assertFalse("Unexpected item " + item + " in selection" + selectionArea,
+                        lastSelection.contains(item.name));
+            }
         }
     }
 
+    private void startSelection(Point p) {
+        model.startSelection(p);
+        mSelectionOrigin = env.createAbsolutePoint(p);
+    }
+
+    private void resizeSelection(Point p) {
+        model.resizeSelection(p);
+        mSelectionPoint = env.createAbsolutePoint(p);
+    }
+
     private void scroll(int dy) {
         assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
         env.verticalOffset += dy;
+        // Correct the cached selection point as well.
+        mSelectionPoint.y += dy;
         model.onScrolled(null, 0, dy);
     }
 
     private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment {
 
-        public int horizontalOffset = 0;
-        public int verticalOffset = 0;
         private final int mNumColumns;
         private final int mNumRows;
         private final int mNumChildren;
+        private final int mSeparatorPosition;
+
+        public int horizontalOffset = 0;
+        public int verticalOffset = 0;
+        private List<Item> items = new ArrayList<>();
 
         public TestEnvironment(int numChildren, int numColumns) {
             mNumChildren = numChildren;
             mNumColumns = numColumns;
-            mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
+            mSeparatorPosition = mNumColumns + 1;
+            mNumRows = setupGrid();
+        }
+
+        private int setupGrid() {
+            // Split the input set into folders and documents. Do this such that there is a
+            // partially-populated row in the middle of the grid, to test corner cases in layout
+            // code.
+            int y = VIEW_PADDING_PX;
+            int i = 0;
+            int numRows = 0;
+            while (i < mNumChildren) {
+                int top = y;
+                int height = CHILD_VIEW_EDGE_PX;
+                int width = CHILD_VIEW_EDGE_PX;
+                for (int j = 0; j < mNumColumns && i < mNumChildren; j++) {
+                    int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX));
+                    items.add(new Item(
+                            Integer.toString(i),
+                            new Rect(
+                                    left,
+                                    top,
+                                    left + width - 1,
+                                    top + height - 1)));
+
+                    // Create a partially populated row at the separator position.
+                    if (++i == mSeparatorPosition) {
+                        break;
+                    }
+                }
+                y += height + VIEW_PADDING_PX;
+                numRows++;
+            }
+
+            return numRows;
         }
 
         private int getTotalHeight() {
@@ -227,8 +341,16 @@
 
         private int getNumItemsInRow(int index) {
             assertTrue(index >= 0 && index < mNumRows);
-            if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) {
-                return mNumChildren % mNumColumns;
+            int mod = mSeparatorPosition % mNumColumns;
+            if (index == (mSeparatorPosition / mNumColumns)) {
+                // The row containing the separator may be incomplete
+                return mod > 0 ? mod : mNumColumns;
+            }
+            // Account for the partial separator row in the final row tally.
+            if (index == mNumRows - 1) {
+                // The last row may be incomplete
+                int finalRowCount = (mNumChildren - mod) % mNumColumns;
+                return finalRowCount > 0 ? finalRowCount : mNumColumns;
             }
 
             return mNumColumns;
@@ -257,21 +379,18 @@
 
         @Override
         public int getAdapterPositionAt(int index) {
-            return index + mNumColumns * (getFirstVisibleRowIndex());
+            // Account for partial rows by actually tallying up the items in hidden rows.
+            int hiddenCount = 0;
+            for (int i = 0; i < getFirstVisibleRowIndex(); i++) {
+                hiddenCount += getNumItemsInRow(i);
+            }
+            return index + hiddenCount;
         }
 
         @Override
         public Rect getAbsoluteRectForChildViewAt(int index) {
-            int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index;
-            int rowIndex = adapterPosition / mNumColumns;
-            int columnIndex = adapterPosition % mNumColumns;
-
-            Rect rect = new Rect();
-            rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
-            rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1;
-            rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
-            rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1;
-            return rect;
+            int adapterPosition = getAdapterPositionAt(index);
+            return items.get(adapterPosition).rect;
         }
 
         @Override
@@ -285,11 +404,6 @@
         }
 
         @Override
-        public int getRowCount() {
-            return mNumRows;
-        }
-
-        @Override
         public void showBand(Rect rect) {
             throw new UnsupportedOperationException();
         }
@@ -328,5 +442,19 @@
         public boolean isLayoutItem(int adapterPosition) {
             return false;
         }
+
+        public static final class Item {
+            public String name;
+            public Rect rect;
+
+            public Item(String n, Rect r) {
+                name = n;
+                rect = r;
+            }
+
+            public String toString() {
+                return name + ": " + rect;
+            }
+        }
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
index 8e624a0..56e54a6 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
@@ -87,11 +87,6 @@
     }
 
     @Override
-    public int getRowCount() {
-        return 0;
-    }
-
-    @Override
     public int getChildCount() {
         return 0;
     }
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 519db66..c2ca998 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -22,8 +22,8 @@
     coreApp="true">
 
     <application android:label="@string/app_name"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <library android:name="android.ext.services"/>
 
diff --git a/packages/ExtShared/AndroidManifest.xml b/packages/ExtShared/AndroidManifest.xml
index e2e81d0..04d865e 100644
--- a/packages/ExtShared/AndroidManifest.xml
+++ b/packages/ExtShared/AndroidManifest.xml
@@ -22,8 +22,8 @@
 
     <application android:label="@string/app_name"
         android:allowBackup="false"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <library android:name="android.ext.shared"/>
 
diff --git a/packages/FakeOemFeatures/AndroidManifest.xml b/packages/FakeOemFeatures/AndroidManifest.xml
index fe74ad8..a66521d 100644
--- a/packages/FakeOemFeatures/AndroidManifest.xml
+++ b/packages/FakeOemFeatures/AndroidManifest.xml
@@ -12,8 +12,8 @@
         android:allowBackup="false"
         android:hardwareAccelerated="true"
         android:label="Fake OEM Features"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <service android:name=".FakeCoreService" android:process=":core"
                 android:label="Fake OEM Core Service" />
diff --git a/packages/FusedLocation/AndroidManifest.xml b/packages/FusedLocation/AndroidManifest.xml
index ed84c0d..a8319ab 100644
--- a/packages/FusedLocation/AndroidManifest.xml
+++ b/packages/FusedLocation/AndroidManifest.xml
@@ -29,8 +29,8 @@
     <application
             android:label="@string/app_label"
             android:process="system"
-            android:forceDeviceEncrypted="true"
-            android:encryptionAware="true">
+            android:defaultToDeviceProtectedStorage="true"
+            android:directBootAware="true">
 
         <uses-library android:name="com.android.location.provider" />
 
diff --git a/packages/InputDevices/AndroidManifest.xml b/packages/InputDevices/AndroidManifest.xml
index 07885ea..9507c9f 100644
--- a/packages/InputDevices/AndroidManifest.xml
+++ b/packages/InputDevices/AndroidManifest.xml
@@ -7,8 +7,8 @@
             android:allowClearUserData="false"
             android:label="@string/app_label"
             android:process="system"
-            android:forceDeviceEncrypted="true"
-            android:encryptionAware="true">
+            android:defaultToDeviceProtectedStorage="true"
+            android:directBootAware="true">
 
         <receiver android:name=".InputDeviceReceiver"
                 android:label="@string/keyboard_layouts_label">
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 54972b4..165fe05 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -46,8 +46,8 @@
         android:process="com.android.systemui"
         android:persistent="true"
         android:supportsRtl="true"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
     </application>
 </manifest>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
similarity index 83%
rename from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
rename to packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
index 55f55b0..83488cd 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package com.android.mtp;
 
 import java.io.IOException;
 
 /**
  * Exception thrown when the device is busy and the requested operation cannon be completed.
  */
-public class BusyDeviceException extends IOException {
+class BusyDeviceException extends IOException {
+    BusyDeviceException() {
+        super("The MTP device is busy.");
+    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 4582226..68c1992 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -30,6 +30,8 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.FileUriExposedException;
+import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
 import android.provider.DocumentsContract.Document;
@@ -41,7 +43,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -324,25 +325,61 @@
         if (DEBUG) {
             Log.d(TAG, "createDocument: " + displayName);
         }
+        final Identifier parentId;
+        final MtpDeviceRecord record;
+        final ParcelFileDescriptor[] pipe;
         try {
-            final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
+            parentId = mDatabase.createIdentifier(parentDocumentId);
             openDevice(parentId.mDeviceId);
-            final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
+            record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
             if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
-                throw new UnsupportedOperationException();
+                throw new UnsupportedOperationException(
+                        "Writing operation is not supported by the device.");
             }
-            final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
-            pipe[0].close();  // 0 bytes for a new document.
-            final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
-                    MtpConstants.FORMAT_ASSOCIATION :
-                    MediaFile.getFormatCode(displayName, mimeType);
-            final MtpObjectInfo info = new MtpObjectInfo.Builder()
-                    .setStorageId(parentId.mStorageId)
-                    .setParent(parentId.mObjectHandle)
-                    .setFormat(formatCode)
-                    .setName(displayName)
-                    .build();
-            final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]);
+            pipe = ParcelFileDescriptor.createReliablePipe();
+            int objectHandle = -1;
+            MtpObjectInfo info = null;
+            try {
+                pipe[0].close();  // 0 bytes for a new document.
+
+                final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
+                        MtpConstants.FORMAT_ASSOCIATION :
+                        MediaFile.getFormatCode(displayName, mimeType);
+                info = new MtpObjectInfo.Builder()
+                        .setStorageId(parentId.mStorageId)
+                        .setParent(parentId.mObjectHandle)
+                        .setFormat(formatCode)
+                        .setName(displayName)
+                        .build();
+
+                final String[] parts = FileUtils.splitFileName(mimeType, displayName);
+                final String baseName = parts[0];
+                final String extension = parts[1];
+                for (int i = 0; i <= 32; i++) {
+                    final MtpObjectInfo infoUniqueName;
+                    if (i == 0) {
+                        infoUniqueName = info;
+                    } else {
+                        infoUniqueName = new MtpObjectInfo.Builder(info).setName(
+                                baseName + " (" + i + ")." + extension).build();
+                    }
+                    try {
+                        objectHandle = mMtpManager.createDocument(
+                                parentId.mDeviceId, infoUniqueName, pipe[1]);
+                        break;
+                    } catch (SendObjectInfoFailure exp) {
+                        // This can be caused when we have an existing file with the same name.
+                        continue;
+                    }
+                }
+            } finally {
+                pipe[1].close();
+            }
+            if (objectHandle == -1) {
+                throw new IllegalArgumentException(
+                        "The file name \"" + displayName + "\" is conflicted with existing files " +
+                        "and the provider failed to find unique name.");
+            }
             final MtpObjectInfo infoWithHandle =
                     new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
             final String documentId = mDatabase.putNewDocument(
@@ -351,9 +388,12 @@
             getDocumentLoader(parentId).clearTask(parentId);
             notifyChildDocumentsChange(parentDocumentId);
             return documentId;
+        } catch (FileNotFoundException | RuntimeException error) {
+            Log.e(TAG, "createDocument", error);
+            throw error;
         } catch (IOException error) {
             Log.e(TAG, "createDocument", error);
-            throw new FileNotFoundException(error.getMessage());
+            throw new IllegalStateException(error);
         }
     }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 0202343..6fb2a78 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -33,7 +33,6 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -190,7 +189,7 @@
         synchronized (device) {
             final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo);
             if (sendObjectInfoResult == null) {
-                throw new IOException("Failed to create a document");
+                throw new SendObjectInfoFailure();
             }
             if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) {
                 if (!device.sendObject(sendObjectInfoResult.getObjectHandle(),
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
similarity index 75%
copy from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
copy to packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
index 55f55b0..db7d777 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package com.android.mtp;
 
 import java.io.IOException;
 
 /**
- * Exception thrown when the device is busy and the requested operation cannon be completed.
+ * Exception thrown when sendObjectInfo failed.
  */
-public class BusyDeviceException extends IOException {
+class SendObjectInfoFailure extends IOException {
+    SendObjectInfoFailure() {
+        super("Failed to MtpDevice#sendObjectInfo.");
+    }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index afcb457..9c1880a 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -30,8 +30,6 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.android.mtp.exceptions.BusyDeviceException;
-
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.Arrays;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 7a6aad6..2d3935b 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -870,39 +870,56 @@
                 // AsyncCommand.AsyncCommandHandler#handleMessage
                 if (isFailed()) {
                     if (DEBUG) {
-                        Log.i(LOG_TAG, "[CALLBACK] on canceled layout command");
+                        Log.i(LOG_TAG, "[CALLBACK] on failed layout command");
                     }
 
                     return;
-                } else {
-                    if (message.what != MSG_ON_LAYOUT_STARTED) {
-                        // No need to force cancel anymore if layout finished
-                        removeForceCancel();
-                    }
                 }
 
-                switch (message.what) {
+                int sequence;
+                int what = message.what;
+                switch (what) {
+                    case MSG_ON_LAYOUT_FINISHED:
+                        removeForceCancel();
+                        sequence = message.arg2;
+                        break;
+                    case MSG_ON_LAYOUT_FAILED:
+                    case MSG_ON_LAYOUT_CANCELED:
+                        removeForceCancel();
+                        // $FALL-THROUGH - message uses the same format as "started"
+                    case MSG_ON_LAYOUT_STARTED:
+                        // Don't remote force-cancel as command is still running and might need to
+                        // be canceled later
+                        sequence = message.arg1;
+                        break;
+                    default:
+                        // not reached
+                        sequence = -1;
+                }
+
+                // If we are canceling any result is treated as a cancel
+                if (isCanceling() && what != MSG_ON_LAYOUT_STARTED) {
+                    what = MSG_ON_LAYOUT_CANCELED;
+                }
+
+                switch (what) {
                     case MSG_ON_LAYOUT_STARTED: {
                         ICancellationSignal cancellation = (ICancellationSignal) message.obj;
-                        final int sequence = message.arg1;
                         handleOnLayoutStarted(cancellation, sequence);
                     } break;
 
                     case MSG_ON_LAYOUT_FINISHED: {
                         PrintDocumentInfo info = (PrintDocumentInfo) message.obj;
                         final boolean changed = (message.arg1 == 1);
-                        final int sequence = message.arg2;
                         handleOnLayoutFinished(info, changed, sequence);
                     } break;
 
                     case MSG_ON_LAYOUT_FAILED: {
                         CharSequence error = (CharSequence) message.obj;
-                        final int sequence = message.arg1;
                         handleOnLayoutFailed(error, sequence);
                     } break;
 
                     case MSG_ON_LAYOUT_CANCELED: {
-                        final int sequence = message.arg1;
                         handleOnLayoutCanceled(sequence);
                     } break;
                 }
@@ -1142,18 +1159,30 @@
                 // AsyncCommand.AsyncCommandHandler#handleMessage
                 if (isFailed()) {
                     if (DEBUG) {
-                        Log.i(LOG_TAG, "[CALLBACK] on canceled write command");
+                        Log.i(LOG_TAG, "[CALLBACK] on failed write command");
                     }
 
                     return;
-                } else {
-                    if (message.what != MSG_ON_WRITE_STARTED) {
-                        // No need to force cancel anymore if write finished
-                        removeForceCancel();
-                    }
                 }
 
-                switch (message.what) {
+                int what = message.what;
+                switch (what) {
+                    case MSG_ON_WRITE_FINISHED:
+                    case MSG_ON_WRITE_FAILED:
+                    case MSG_ON_WRITE_CANCELED:
+                        removeForceCancel();
+                    case MSG_ON_WRITE_STARTED:
+                        // Don't remote force-cancel as command is still running and might need to
+                        // be canceled later
+                        break;
+                }
+
+                // If we are canceling any result is treated as a cancel
+                if (isCanceling() && what != MSG_ON_WRITE_STARTED) {
+                    what = MSG_ON_WRITE_CANCELED;
+                }
+
+                switch (what) {
                     case MSG_ON_WRITE_STARTED: {
                         ICancellationSignal cancellation = (ICancellationSignal) message.obj;
                         final int sequence = message.arg1;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 606f4eb..645e182 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -20,6 +20,8 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.print.PageRange;
 import android.print.PrintAttributes.MediaSize;
@@ -570,7 +572,14 @@
             if (DEBUG) {
                 Log.i(LOG_TAG, "Requesting pages: " + Arrays.toString(mRequestedPages));
             }
-            mCallbacks.onRequestContentUpdate();
+
+            // This call might come from a recylerview that is currently updating. Hence delay to
+            // after the update
+            (new Handler(Looper.getMainLooper())).post(new Runnable() {
+                @Override public void run() {
+                    mCallbacks.onRequestContentUpdate();
+                }
+            });
         }
     }
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index ad4823e..4e1180d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -159,6 +159,7 @@
     private static final int STATE_PRINTER_UNAVAILABLE = 6;
     private static final int STATE_UPDATE_SLOW = 7;
     private static final int STATE_PRINT_COMPLETED = 8;
+    private static final int STATE_FINISHING = 9;
 
     private static final int UI_STATE_PREVIEW = 0;
     private static final int UI_STATE_ERROR = 1;
@@ -2029,11 +2030,17 @@
     }
 
     private void doFinish() {
-        if (mPrintedDocument.isUpdating()) {
+        if (mPrintedDocument != null && mPrintedDocument.isUpdating()) {
             // The printedDocument will call doFinish() when the current command finishes
             return;
         }
 
+        if (mState == STATE_FINISHING) {
+            return;
+        }
+
+        mState = STATE_FINISHING;
+
         if (mPrinterRegistry != null) {
             mPrinterRegistry.setTrackedPrinter(null);
         }
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e4c2cbc..1aee490 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -687,7 +687,7 @@
     <!-- Developer settings: select WebView provider dialog title [CHAR LIMIT=30] -->
     <string name="select_webview_provider_dialog_title">Set WebView implementation</string>
     <!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
-    <string name="select_webview_provider_toast_text">The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated.</string>
+    <string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string>
 
     <!-- Developer settings screen, convert userdata to file encryption option name -->
     <string name="convert_to_file_encryption">Convert to file encryption</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index fa2226d..74c1ebd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -151,10 +151,17 @@
         if (sSystemSignature == null) {
             sSystemSignature = new Signature[]{ getSystemSignature(pm) };
         }
-        return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg));
+        if (sPermissionControllerPackageName == null) {
+            sPermissionControllerPackageName = pm.getPermissionControllerPackageName();
+        }
+        return (sSystemSignature[0] != null
+                        && sSystemSignature[0].equals(getFirstSignature(pkg)))
+                || (sPermissionControllerPackageName != null
+                        && sPermissionControllerPackageName.equals(pkg.packageName));
     }
 
     private static Signature[] sSystemSignature;
+    private static String sPermissionControllerPackageName;
 
     private static Signature getFirstSignature(PackageInfo pkg) {
         if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 7a1c741..ce69c5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -103,16 +103,6 @@
     }
 
     @Override
-    public void onBackPressed() {
-        if (mShowingMenu) {
-            // If we are showing the menu, then we are a top level activity and the back should
-            // kick back to settings home.
-            openTile(null);
-        }
-        super.onBackPressed();
-    }
-
-    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
                 && mDrawerAdapter.getCount() != 0) {
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index ba991fb..6c06d05 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -9,8 +9,8 @@
                  android:backupAgent="SettingsBackupAgent"
                  android:killAfterRestore="false"
                  android:icon="@mipmap/ic_launcher_settings"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
 
         <provider android:name="SettingsProvider"
                   android:authorities="settings"
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5b865f9..0c35573 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -113,8 +113,8 @@
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
 
     <application android:label="@string/app_label"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
         <provider
             android:name="android.support.v4.content.FileProvider"
             android:authorities="com.android.shell"
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 334035c..073cf14 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -167,8 +167,8 @@
         android:process="com.android.systemui"
         android:supportsRtl="true"
         android:theme="@style/systemui_theme"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
         <!-- Keep theme in sync with SystemUIApplication.onCreate().
              Setting the theme on the application does not affect views inflated by services.
              The application theme is set again from onCreate to take effect for those views. -->
diff --git a/packages/SystemUI/res/drawable/ic_send.xml b/packages/SystemUI/res/drawable/ic_send.xml
index b1c7914..6ce3672 100644
--- a/packages/SystemUI/res/drawable/ic_send.xml
+++ b/packages/SystemUI/res/drawable/ic_send.xml
@@ -14,6 +14,7 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="48.0"
diff --git a/packages/SystemUI/res/drawable/recents_empty.xml b/packages/SystemUI/res/drawable/recents_empty.xml
new file mode 100644
index 0000000..5506de1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_empty.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="100dp"
+    android:height="132dp"
+    android:viewportWidth="100"
+    android:viewportHeight="132">
+
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,68.67H13.09c-4.96,0-9,4.04-9,9V119c0,4.96,4.04,9,9,9h73.82c4.96,0,9-4.04,9-9V77.67
+C95.91,72.7,91.87,68.67,86.91,68.67z M27.59,77.27h26.72v3.94H27.59V77.27z
+M18.73,74.74c2.49,0,4.5,2.01,4.5,4.5
+c0,2.49-2.01,4.5-4.5,4.5s-4.5-2.01-4.5-4.5C14.23,76.75,16.24,74.74,18.73,74.74z
+M89.91,119c0,1.65-1.35,3-3,3H13.09 c-1.65,0-3-1.35-3-3V88.67h79.82V119z" />
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,36.3H13.09c-4.96,0-9,4.04-9,9v23c1.65-1.58,3.71-2.73,6-3.28v-9.08h79.82v9.08
+c2.29,0.55,4.35,1.69,6,3.28v-23C95.91,40.34,91.87,36.3,86.91,36.3z
+M18.73,51.38c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,51.38,18.73,51.38z M54.31,48.84H27.59v-3.94h26.72V48.84z" />
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,4H13.09c-4.96,0-9,4.04-9,9v22.94c1.65-1.58,3.71-2.73,6-3.28V24h79.82v8.67
+c2.29,0.55,4.35,1.69,6,3.28V13C95.91,8.04,91.87,4,86.91,4z
+M18.73,18.5c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,18.5,18.73,18.5z M54.31,15.97H27.59v-3.94h26.72V15.97z" />
+    <path
+        android:pathData="M 0 0 H 100 V 132 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
index 5a6553f..9c2c0ab 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -27,29 +27,19 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingEnd="12dp"
-            android:background="@android:color/white"
-            android:textColor="#D9000000"
+            android:textColor="@color/ksh_keyword_color"
             android:textSize="16sp"
             android:maxLines="5"
             android:singleLine="false"
             android:scrollHorizontally="false"
-            android:layout_alignParentStart="true"
-            android:minWidth="100dp"
-            android:maxWidth="260dp"/>
-    <!--TODO: introduce and use a layout that allows wrapping and right align -->
-    <LinearLayout
+            android:layout_alignParentStart="true"/>
+    <com.android.systemui.statusbar.KeyboardShortcutKeysLayout
             android:id="@+id/keyboard_shortcuts_item_container"
             android:layout_toEndOf="@+id/keyboard_shortcuts_keyword"
             android:orientation="horizontal"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:background="@android:color/white"
             android:layout_alignParentEnd="true"
-            android:gravity="end"
             android:textSize="14sp"
-            android:paddingStart="0dp"
-            android:paddingEnd="0dp"
-            android:scrollHorizontally="false"
-            android:minWidth="100dp"
-            android:maxWidth="260dp"/>
+            android:scrollHorizontally="false"/>
 </RelativeLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
index 80a478a..6cb8470 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
@@ -22,4 +22,4 @@
           android:paddingStart="24dp"
           android:paddingTop="20dp"
           android:paddingEnd="24dp"
-          android:paddingBottom="13dp" />
+          android:paddingBottom="13dp"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
index f73ee15..7aba1cf 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
@@ -17,7 +17,7 @@
 
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="488dp"
+    android:layout_width="@dimen/ksh_layout_width"
     android:layout_height="wrap_content">
     <LinearLayout
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index df46271..c062b6d 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -30,6 +30,7 @@
         android:padding="16dp"
         android:clickable="true"
         android:background="?android:attr/selectableItemBackground"
+        android:contentDescription="@*android:string/action_bar_up_description"
         android:src="?android:attr/homeAsUpIndicator" />
 
     <TextView
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index b2c0331..53d9cc5 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -16,10 +16,12 @@
 
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
     android:layout_gravity="center"
     android:gravity="center"
+    android:drawableTop="@drawable/recents_empty"
+    android:drawablePadding="25dp"
     android:textSize="16sp"
     android:textColor="#ffffffff"
     android:text="@string/recents_empty_message"
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 3a7c1d1..567e009 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -18,7 +18,6 @@
     android:id="@+id/recents_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/recents_tv_background_gradient"
     android:clipChildren="false"
     android:clipToPadding="false"
     android:layoutDirection="rtl">
diff --git a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index c5b1a7a..54e97da 100644
--- a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -59,7 +59,7 @@
         <ImageView
                 android:id="@+id/card_view_thumbnail"
                 android:layout_width="match_parent"
-                android:layout_height="@dimen/recents_tv_card_height"
+                android:layout_height="@dimen/recents_tv_screenshot_height"
                 android:scaleType="centerCrop"
                 android:gravity="center"
                 android:layout_alignParentTop="true"
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 75195c4..7460201 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -43,6 +43,7 @@
             android:singleLine="true"
             android:ellipsize="start"
             android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
+            android:textIsSelectable="true"
             android:imeOptions="actionSend|flagNoExtractUi" />
 
     <FrameLayout
@@ -62,6 +63,7 @@
                 android:paddingBottom="12dp"
                 android:id="@+id/remote_input_send"
                 android:src="@drawable/ic_send"
+                android:contentDescription="@*android:string/ime_action_send"
                 android:tint="@color/remote_input_send"
                 android:tintMode="src_in"
                 android:background="@drawable/ripple_drawable" />
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index a2fa3b9..66963c4 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -104,4 +104,7 @@
 
     <!-- The side padding for the task stack. -->
     <dimen name="recents_stack_left_right_padding">64dp</dimen>
+
+    <!-- Keyboard shortcuts helper -->
+    <dimen name="ksh_layout_width">488dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d65ab04..a3f8b85 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -155,6 +155,8 @@
     <color name="default_remote_input_background">@*android:color/notification_default_color</color>
     <color name="remote_input_hint">#4dffffff</color>
 
+    <color name="remote_input_accent">#eeeeee</color>
+
     <color name="qs_tile_tint_unavailable">#40ffffff</color>
     <color name="qs_tile_tint_inactive">#4dffffff</color>
     <color name="qs_tile_tint_active">#ffffffff</color>
@@ -165,6 +167,7 @@
     <!-- Keyboard shortcuts colors -->
     <color name="ksh_system_group_color">#ff00bcd4</color>
     <color name="ksh_application_group_color">#fff44336</color>
+    <color name="ksh_keyword_color">#d9000000</color>
 
     <!-- Background color of edit overflow -->
     <color name="qs_edit_overflow_bg">#455A64</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6a9f456..8b433f9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -639,4 +639,7 @@
 
     <dimen name="battery_detail_graph_space_top">27dp</dimen>
     <dimen name="battery_detail_graph_space_bottom">27dp</dimen>
+
+    <!-- Keyboard shortcuts helper -->
+    <dimen name="ksh_layout_width">@dimen/match_parent</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index b589110..6b153d1 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -19,7 +19,7 @@
 <resources>
     <!-- Dimens for recents card in the recents view on tv -->
     <dimen name="recents_tv_card_width">268dip</dimen>
-    <dimen name="recents_tv_card_height">151dip</dimen>
+    <dimen name="recents_tv_screenshot_height">151dip</dimen>
     <dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
     <dimen name="recents_tv_banner_width">114dip</dimen>
     <dimen name="recents_tv_banner_height">64dip</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8af413c..5295ccb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -715,7 +715,9 @@
     <string name="quick_settings_work_mode_label">Work mode</string>
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
-    <string name="recents_empty_message">Your recent screens appear here</string>
+    <string name="recents_empty_message">No recent items</string>
+    <!-- Recents: The empty recents string after dismissing all tasks. [CHAR LIMIT=NONE] -->
+    <string name="recents_empty_message_dismissed_all">You\'ve cleared everything</string>
     <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
     <string name="recents_app_info_button_label">Application Info</string>
     <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] -->
@@ -1184,11 +1186,6 @@
     <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
     <string name="qs_paging" translatable="false">Use the new Quick Settings</string>
 
-    <!-- Disables fast-toggling recents via the recents button. DO NOT TRANSLATE -->
-    <string name="overview_disable_fast_toggle_via_button">Disable fast toggle</string>
-    <!-- Description for the toggle for fast-toggling recents via the recents button. DO NOT TRANSLATE -->
-    <string name="overview_disable_fast_toggle_via_button_desc">Disable launch timeout while paging</string>
-
     <!-- Toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=60]-->
     <string name="overview_nav_bar_gesture">Enable split-screen swipe-up gesture</string>
     <!-- Description for the toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=NONE]-->
@@ -1435,6 +1432,9 @@
     <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
     <string name="drag_to_add_tiles">Drag to add tiles</string>
 
+    <!-- Label for area where tiles can be dragged in to [CHAR LIMIT=60] -->
+    <string name="drag_to_remove_tiles">Drag here to remove</string>
+
     <!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] -->
     <string name="qs_edit">Edit</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2660926..b0c1e95 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -201,8 +201,8 @@
         <item name="android:colorControlActivated">@color/system_accent_color</item>
     </style>
 
-    <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault">
-        <item name="android:colorControlActivated">@android:color/white</item>
+    <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
+        <item name="android:colorAccent">@color/remote_input_accent</item>
     </style>
 
     <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml
index 1fcc9e4..6a72e54 100644
--- a/packages/SystemUI/res/values/values_tv.xml
+++ b/packages/SystemUI/res/values/values_tv.xml
@@ -15,4 +15,5 @@
 -->
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <item format="float" type="integer" name="unselected_scale">1.0</item>
+    <item format="float" type="integer" name="selected_scale">1.1</item>
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index ddc03a3..a130cf9 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -138,11 +138,6 @@
         android:title="@string/other" >
 
         <com.android.systemui.tuner.TunerSwitch
-            android:key="overview_disable_fast_toggle_via_button"
-            android:title="@string/overview_disable_fast_toggle_via_button"
-            android:summary="@string/overview_disable_fast_toggle_via_button_desc" />
-
-        <com.android.systemui.tuner.TunerSwitch
             android:key="overview_nav_bar_gesture"
             android:title="@string/overview_nav_bar_gesture"
             android:summary="@string/overview_nav_bar_gesture_desc" />
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 358674c..aa3f6e5 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -535,31 +535,43 @@
         boolean nowExpanded;
         int naturalHeight = mScaler.getNaturalHeight();
         if (wasClosed) {
-            nowExpanded = (force || currentHeight > mOldHeight);
+            nowExpanded = (force || currentHeight > mOldHeight && velocity >= 0);
         } else {
-            nowExpanded = !force && currentHeight >= mOldHeight;
+            nowExpanded = !force && (currentHeight >= mOldHeight || velocity > 0);
         }
         nowExpanded |= mNaturalHeight == mSmallSize;
         if (mScaleAnimation.isRunning()) {
             mScaleAnimation.cancel();
         }
-        mCallback.setUserExpandedChild(mResizedView, nowExpanded);
         mCallback.expansionStateChanged(false);
         float targetHeight = nowExpanded ? naturalHeight : mSmallSize;
         if (targetHeight != currentHeight) {
             mScaleAnimation.setFloatValues(targetHeight);
             mScaleAnimation.setupStartValues();
             final View scaledView = mResizedView;
+            final boolean expand = nowExpanded;
             mScaleAnimation.addListener(new AnimatorListenerAdapter() {
+                public boolean mCancelled;
+
                 @Override
                 public void onAnimationEnd(Animator animation) {
+                    if (!mCancelled) {
+                        mCallback.setUserExpandedChild(scaledView, expand);
+                    }
                     mCallback.setUserLockedChild(scaledView, false);
                     mScaleAnimation.removeListener(this);
                 }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mCancelled = true;
+                }
             });
+            velocity = nowExpanded == velocity >= 0 ? velocity : 0;
             mFlingAnimationUtils.apply(mScaleAnimation, currentHeight, targetHeight, velocity);
             mScaleAnimation.start();
         } else {
+            mCallback.setUserExpandedChild(mResizedView, nowExpanded);
             mCallback.setUserLockedChild(mResizedView, false);
         }
 
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 72a59d7..aeca840 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -128,6 +128,7 @@
     public void hide(int x, int y) {
         if (isShown) {
             isShown = false;
+            mToolbar.dismissPopupMenus();
             setCustomizing(false);
             save();
             mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
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 d9b3b3f..03c2a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -17,6 +17,7 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.drawable.ColorDrawable;
+import android.os.Handler;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
 import android.support.v7.widget.RecyclerView;
@@ -28,6 +29,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
+import android.widget.TextView;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSIconView;
 import com.android.systemui.qs.QSTileView;
@@ -50,6 +52,7 @@
 
     private final Context mContext;
 
+    private final Handler mHandler = new Handler();
     private final List<TileInfo> mTiles = new ArrayList<>();
     private final ItemTouchHelper mItemTouchHelper;
     private int mDividerIndex;
@@ -153,7 +156,12 @@
 
     @Override
     public void onBindViewHolder(final Holder holder, int position) {
-        if (holder.getItemViewType() == TYPE_EDIT) return;
+        if (holder.getItemViewType() == TYPE_EDIT) {
+            ((TextView) holder.itemView.findViewById(android.R.id.title)).setText(
+                    mCurrentDrag != null ? R.string.drag_to_remove_tiles
+                    : R.string.drag_to_add_tiles);
+            return;
+        }
 
         TileInfo info = mTiles.get(position);
         holder.mTileView.onStateChanged(info.state);
@@ -250,11 +258,18 @@
             super.onSelectedChanged(viewHolder, actionState);
             if (mCurrentDrag != null) {
                 mCurrentDrag.stopDrag();
+                mCurrentDrag = null;
             }
             if (viewHolder != null) {
                 mCurrentDrag = (Holder) viewHolder;
                 mCurrentDrag.startDrag();
             }
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    notifyItemChanged(mDividerIndex);
+                }
+            });
         }
 
         @Override
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 db686a8..9156f3a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -75,7 +75,8 @@
         mUser = ActivityManager.getCurrentUser();
         try {
             PackageManager pm = mContext.getPackageManager();
-            ServiceInfo info = pm.getServiceInfo(mComponent, 0);
+            ServiceInfo info = pm.getServiceInfo(mComponent,
+                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
             mTile.setIcon(android.graphics.drawable.Icon
                     .createWithResource(mComponent.getPackageName(), info.icon));
             mTile.setLabel(info.loadLabel(pm));
@@ -88,6 +89,17 @@
         }
     }
 
+    @Override
+    public boolean isAvailable() {
+        try {
+            ServiceInfo info = mContext.getPackageManager().getServiceInfo(mComponent,
+                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
     public int getUser() {
         return mUser;
     }
@@ -211,11 +223,15 @@
     @Override
     protected void handleUpdateState(State state, Object arg) {
         Drawable drawable = mTile.getIcon().loadDrawable(mContext);
-        int color = mContext.getColor(getColor(mTile.getState()));
+        int tileState = mTile.getState();
+        if (mServiceManager.hasPendingBind()) {
+            tileState = Tile.STATE_UNAVAILABLE;
+        }
+        int color = mContext.getColor(getColor(tileState));
         drawable.setTint(color);
         state.icon = new DrawableIcon(drawable);
         state.label = mTile.getLabel();
-        if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
+        if (tileState == Tile.STATE_UNAVAILABLE) {
             state.label = new SpannableStringBuilder().append(state.label,
                     new ForegroundColorSpan(color),
                     SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 2aad161..8910d44 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -249,6 +249,8 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+        filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
+        mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
         mReceiverRegistered = true;
     }
 
@@ -261,10 +263,12 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         if (DEBUG) Log.d(TAG, "onReceive: " + intent);
-        Uri data = intent.getData();
-        String pkgName = data.getEncodedSchemeSpecificPart();
-        if (!Objects.equal(pkgName, mIntent.getComponent().getPackageName())) {
-            return;
+        if (!Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
+            Uri data = intent.getData();
+            String pkgName = data.getEncodedSchemeSpecificPart();
+            if (!Objects.equal(pkgName, mIntent.getComponent().getPackageName())) {
+                return;
+            }
         }
         stopPackageListening();
         if (mBound) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 5cf1e21..664ddd6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -53,6 +53,9 @@
     private long mLastUpdate;
     private int mType;
     private boolean mShowingDialog;
+    // Whether we have a pending bind going out to the service without a response yet.
+    // This defaults to true to ensure tiles start out unavailable.
+    private boolean mPendingBind = true;
 
     TileServiceManager(TileServices tileServices, Handler handler, ComponentName component) {
         this(tileServices, handler, new TileLifecycleManager(handler,
@@ -132,11 +135,20 @@
         }
     }
 
+    public boolean hasPendingBind() {
+        return mPendingBind;
+    }
+
+    public void clearPendingBind() {
+        mPendingBind = false;
+    }
+
     private void bindService() {
         if (mBound) {
             Log.e(TAG, "Service already bound");
             return;
         }
+        mPendingBind = true;
         mBound = true;
         mJustBound = true;
         mHandler.postDelayed(mJustBoundOver, MIN_BIND_TIME);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index bfa4a32..5bb2a35 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -182,7 +182,9 @@
         CustomTile customTile = getTileForComponent(componentName);
         if (customTile != null) {
             synchronized (mServices) {
-                mServices.get(customTile).setLastUpdate(System.currentTimeMillis());
+                final TileServiceManager tileServiceManager = mServices.get(customTile);
+                tileServiceManager.clearPendingBind();
+                tileServiceManager.setLastUpdate(System.currentTimeMillis());
             }
             customTile.updateState(tile);
             customTile.refreshState();
@@ -190,6 +192,20 @@
     }
 
     @Override
+    public void onStartSuccessful(Tile tile) {
+        ComponentName componentName = tile.getComponentName();
+        verifyCaller(componentName.getPackageName());
+        CustomTile customTile = getTileForComponent(componentName);
+        if (customTile != null) {
+            synchronized (mServices) {
+                final TileServiceManager tileServiceManager = mServices.get(customTile);
+                tileServiceManager.clearPendingBind();
+            }
+            customTile.refreshState();
+        }
+    }
+
+    @Override
     public void onShowDialog(Tile tile) {
         ComponentName componentName = tile.getComponentName();
         verifyCaller(componentName.getPackageName());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 473956f..aab45b5d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -361,7 +362,8 @@
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         if (!loadPlan.hasTasks()) {
-            loader.preloadTasks(loadPlan, -1, launchState.launchedFromHome);
+            loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
+                    launchState.launchedFromHome);
         }
 
         RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -434,6 +436,13 @@
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        EventBus.getDefault().send(new ConfigurationChangedEvent());
+    }
+
+    @Override
     protected void onStop() {
         super.onStop();
 
@@ -740,7 +749,7 @@
     public final void onBusEvent(AllTaskViewsDismissedEvent event) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (ssp.hasDockedTask()) {
-            mRecentsView.showEmptyView();
+            mRecentsView.showEmptyView(event.msgResId);
         } else {
             // Just go straight home (no animation necessary because there are no more task views)
             dismissRecentsToHome(false /* animateTaskViews */);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 6feda81..40bf6d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -41,6 +41,8 @@
         public static final boolean EnableHistory = false;
         // Overrides the Tuner flags and enables the timeout
         private static final boolean EnableFastToggleTimeout = false;
+        // Overrides the Tuner flags and enables the paging via the Recents button
+        private static final boolean EnablePaging = false;
 
         // Enables us to create mock recents tasks
         public static final boolean EnableMockTasks = false;
@@ -54,10 +56,6 @@
         public static final int MockTaskGroupsTaskCount = 12;
     }
 
-    private static final String KEY_ENABLE_PAGING = "overview_enable_paging";
-
-    private boolean mEnablePaging;
-
     /**
      * We read the prefs once when we start the activity, then update them as the tuner changes
      * the flags.
@@ -65,7 +63,6 @@
     public RecentsDebugFlags(Context context) {
         // Register all our flags, this will also call onTuningChanged() for each key, which will
         // initialize the current state of each flag
-        TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING);
     }
 
     /**
@@ -83,16 +80,11 @@
      * @return whether we are enabling paging.
      */
     public boolean isPagingEnabled() {
-        return mEnablePaging;
+        return Static.EnablePaging;
     }
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        switch (key) {
-            case KEY_ENABLE_PAGING:
-                mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0);
-                break;
-        }
         EventBus.getDefault().send(new DebugFlagsChangedEvent());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index d864df8..9be24de 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -66,6 +66,7 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskGrouping;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.TaskCardView;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackView;
 import com.android.systemui.recents.views.TaskStackViewScroller;
@@ -166,6 +167,7 @@
     boolean mCanReuseTaskStackViews = true;
     boolean mDraggingInRecents;
     boolean mLaunchedWhileDocking;
+    private boolean mIsRunningOnTv;
 
     // Task launching
     Rect mSearchBarBounds = new Rect();
@@ -230,8 +232,10 @@
         UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
             mRecentsIntentActivityName = RECENTS_TV_ACTIVITY;
+            mIsRunningOnTv = true;
         } else {
             mRecentsIntentActivityName = RECENTS_ACTIVITY;
+            mIsRunningOnTv = false;
         }
     }
 
@@ -793,6 +797,22 @@
         }
     }
 
+    /**
+     * Creates the activity options for an app->recents transition on TV.
+     */
+    private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
+            ActivityManager.RunningTaskInfo topTask) {
+        Bitmap thumbnail = mThumbnailTransitionBitmapCache;
+        Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
+        if (thumbnail != null) {
+            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+                    null, (int) rect.left, (int) rect.top,
+                    (int) rect.width(), (int) rect.height(), mHandler, null);
+        }
+        // If both the screenshot and thumbnail fails, then just fall back to the default transition
+        return getUnknownTransitionActivityOptions();
+    }
+
     private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
             TaskViewTransform toTransform) {
         Bitmap thumbnail;
@@ -872,6 +892,11 @@
             boolean isTopTaskHome, boolean animate) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
 
+        // If we are on TV, divert to a different helper method
+        if (mIsRunningOnTv) {
+            setUpAndStartTvRecents(topTask, isTopTaskHome, animate);
+            return;
+        }
         // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
         // should always preload the tasks now. If we are dragging in recents, reload them as
         // the stacks might have changed.
@@ -947,6 +972,90 @@
     }
 
     /**
+     * Used to set up the animations of Tv Recents, then start the Recents Activity.
+     * TODO: Add the Transitions for Home -> Recents TV
+     * TODO: Shift Transition code to separate class under /tv directory and access
+     *              from here
+     */
+    private void setUpAndStartTvRecents(ActivityManager.RunningTaskInfo topTask,
+                                      boolean isTopTaskHome, boolean animate) {
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+
+        // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
+        // should always preload the tasks now. If we are dragging in recents, reload them as
+        // the stacks might have changed.
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
+            // Create a new load plan if preloadRecents() was never triggered
+            sInstanceLoadPlan = loader.createLoadPlan(mContext);
+        }
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
+            loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
+        }
+        TaskStack stack = sInstanceLoadPlan.getTaskStack();
+
+        // Update the header bar if necessary
+        updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+
+        // Prepare the dummy stack for the transition
+        TaskStackLayoutAlgorithm.VisibilityReport stackVr =
+                mDummyStackView.computeStackVisibilityReport();
+
+        if (!animate) {
+            ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
+            startRecentsActivity(topTask, opts, false /* fromHome */,
+                    false /* fromSearchHome */, false /* fromThumbnail*/, stackVr);
+            return;
+        }
+
+        boolean hasRecentTasks = stack.getTaskCount() > 0;
+        boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
+
+        if (useThumbnailTransition) {
+            // Try starting with a thumbnail transition
+            ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
+            if (opts != null) {
+                startRecentsActivity(topTask, opts, false /* fromHome */,
+                        false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
+            } else {
+                // Fall through below to the non-thumbnail transition
+                useThumbnailTransition = false;
+            }
+        }
+
+        if (!useThumbnailTransition) {
+            // If there is no thumbnail transition, but is launching from home into recents, then
+            // use a quick home transition and do the animation from home
+            if (hasRecentTasks) {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                String homeActivityPackage = ssp.getHomeActivityPackageName();
+                String searchWidgetPackage = null;
+                if (RecentsDebugFlags.Static.EnableSearchBar) {
+                    searchWidgetPackage = Prefs.getString(mContext,
+                            Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
+                } else {
+                    AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget();
+                    if (searchWidgetInfo != null) {
+                        searchWidgetPackage = searchWidgetInfo.provider.getPackageName();
+                    }
+                }
+
+                // Determine whether we are coming from a search owned home activity
+                boolean fromSearchHome = (homeActivityPackage != null) &&
+                        homeActivityPackage.equals(searchWidgetPackage);
+                ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
+                startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
+                        false /* fromThumbnail */, stackVr);
+            } else {
+                // Otherwise we do the normal fade from an unknown source
+                ActivityOptions opts = getUnknownTransitionActivityOptions();
+                startRecentsActivity(topTask, opts, true /* fromHome */,
+                        false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
+            }
+        }
+        mLastToggleTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
      * Starts the recents activity.
      */
     private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
index cf74519..0352161 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
@@ -22,5 +22,10 @@
  * This is sent whenever all the task views in a stack have been dismissed.
  */
 public class AllTaskViewsDismissedEvent extends EventBus.Event {
-    // Simple event
+
+    public final int msgResId;
+
+    public AllTaskViewsDismissedEvent(int msgResId) {
+        this.msgResId = msgResId;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index 5eeda72..16385c9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -245,7 +245,7 @@
             if (row.getViewType() == TASK_ROW_VIEW_TYPE) {
                 TaskRow taskRow = (TaskRow) row;
                 Task task = taskRow.task;
-                mStack.removeTask(task, AnimationProps.IMMEDIATE);
+                mStack.removeTask(task, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
                 EventBus.getDefault().send(new DeleteTaskDataEvent(task));
                 i = removeTaskRow(i);
             }
@@ -326,7 +326,7 @@
     public void onTaskRemoved(Task task, int position) {
         // Since this is removed from the history, we need to update the stack as well to ensure
         // that the model is correct. Since the stack is hidden, we can update it immediately.
-        mStack.removeTask(task, AnimationProps.IMMEDIATE);
+        mStack.removeTask(task, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
         removeTaskRow(position);
         if (mRows.isEmpty()) {
             dismissHistory();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 5e1af12..ee4d95e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -268,6 +268,14 @@
     BitmapDrawable mDefaultIcon;
     Bitmap mDefaultThumbnail;
 
+    private TaskKeyLruCache.EvictionCallback mClearActivityInfoOnEviction =
+            new TaskKeyLruCache.EvictionCallback() {
+        @Override
+        public void onEntryEvicted(Task.TaskKey key) {
+            mActivityInfoCache.remove(key.getComponent());
+        }
+    };
+
     public RecentsTaskLoader(Context context) {
         Resources res = context.getResources();
         mDefaultTaskBarBackgroundColor =
@@ -292,10 +300,11 @@
         // Initialize the proxy, cache and loaders
         int numRecentTasks = ActivityManager.getMaxRecentTasksStatic();
         mLoadQueue = new TaskResourceLoadQueue();
-        mIconCache = new TaskKeyLruCache<>(iconCacheSize);
+        mIconCache = new TaskKeyLruCache<>(iconCacheSize, mClearActivityInfoOnEviction);
         mThumbnailCache = new TaskKeyLruCache<>(thumbnailCacheSize);
-        mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks);
-        mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks);
+        mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction);
+        mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks,
+                mClearActivityInfoOnEviction);
         mActivityInfoCache = new LruCache(numRecentTasks);
         mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mThumbnailCache,
                 mDefaultThumbnail, mDefaultIcon);
@@ -375,7 +384,6 @@
         mIconCache.remove(t.key);
         mActivityLabelCache.remove(t.key);
         mContentDescriptionCache.remove(t.key);
-        mActivityInfoCache.remove(t.key.getComponent());
         if (notifyTaskDataUnloaded) {
             t.notifyTaskDataUnloaded(null, mDefaultIcon);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
index d433b6c..748d8ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
@@ -30,16 +30,29 @@
  */
 public class TaskKeyLruCache<V> {
 
+    public interface EvictionCallback {
+        public void onEntryEvicted(Task.TaskKey key);
+    }
+
     private static final String TAG = "TaskKeyLruCache";
 
     private final SparseArray<Task.TaskKey> mKeys = new SparseArray<>();
     private final LruCache<Integer, V> mCache;
+    private final EvictionCallback mEvictionCallback;
 
     public TaskKeyLruCache(int cacheSize) {
+        this(cacheSize, null);
+    }
+
+    public TaskKeyLruCache(int cacheSize, EvictionCallback evictionCallback) {
+        mEvictionCallback = evictionCallback;
         mCache = new LruCache<Integer, V>(cacheSize) {
 
             @Override
             protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) {
+                if (mEvictionCallback != null) {
+                    mEvictionCallback.onEntryEvicted(mKeys.get(taskId));
+                }
                 mKeys.remove(taskId);
             }
         };
@@ -84,8 +97,9 @@
 
     /** Removes a cache entry for a specific key. */
     final void remove(Task.TaskKey key) {
-        mKeys.remove(key.id);
+        // Remove the key after the cache value because we need it to make the callback
         mCache.remove(key.id);
+        mKeys.remove(key.id);
     }
 
     /** Removes all the entries in the cache. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 4d1c552..193bfff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -219,7 +219,7 @@
          * Notifies when a task has been removed from the stack.
          */
         void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
-            Task newFrontMostTask, AnimationProps animation);
+            Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture);
 
         /**
          * Notifies when a task has been removed from the history.
@@ -513,14 +513,15 @@
      * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on
      * how they should update themselves.
      */
-    public void removeTask(Task t, AnimationProps animation) {
+    public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) {
         if (mStackTaskList.contains(t)) {
             boolean wasFrontMostTask = (getStackFrontMostTask(false /* includeFreeform */) == t);
             removeTaskImpl(mStackTaskList, t);
             Task newFrontMostTask = getStackFrontMostTask(false  /* includeFreeform */);
             if (mCb != null) {
                 // Notify that a task has been removed
-                mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask, animation);
+                mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask, animation,
+                        fromDockGesture);
             }
         } else if (mHistoryTaskList.contains(t)) {
             removeTaskImpl(mHistoryTaskList, t);
@@ -558,9 +559,9 @@
                 if (notifyStackChanges) {
                     // If we are notifying, then remove the task now, otherwise the raw task list
                     // will be reset at the end of this method
-                    removeTask(task, AnimationProps.IMMEDIATE);
+                    removeTask(task, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
                     mCb.onStackTaskRemoved(this, task, i == (taskCount - 1), null,
-                            AnimationProps.IMMEDIATE);
+                            AnimationProps.IMMEDIATE, false /* fromDockGesture */);
                 }
             }
             task.setGroup(null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index 48a1904..365b29d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -29,6 +29,7 @@
 
 public class ViewFocusAnimator implements View.OnFocusChangeListener {
     private final float mUnselectedScale;
+    private final float mSelectedScale;
     private final float mSelectedScaleDelta;
     private final float mUnselectedZ;
     private final float mSelectedZDelta;
@@ -49,8 +50,9 @@
         TypedValue out = new TypedValue();
         res.getValue(R.integer.unselected_scale, out, true);
         mUnselectedScale = out.getFloat();
-        mSelectedScaleDelta = res.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1) -
-                mUnselectedScale;
+        res.getValue(R.integer.selected_scale, out, true);
+        mSelectedScale = out.getFloat();
+        mSelectedScaleDelta = mSelectedScale - mUnselectedScale;
 
         mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
         mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
index ef8d48e..bd3143f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -16,10 +16,8 @@
 package com.android.systemui.recents.tv.views;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -121,10 +119,10 @@
             };
         }
         try {
-            Rect taskRect = taskView.getGlobalRect();
+            Rect taskRect = taskView.getFocusedThumbnailRect();
             WindowManagerGlobal.getWindowManagerService()
-                    .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
-                            taskRect.top, callback, true);
+                    .overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left,
+                            taskRect.top, taskRect.width(), taskRect.height(), callback, true);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to override transition: " + e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 7d8a3ce..5775b60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -16,8 +16,13 @@
 package com.android.systemui.recents.tv.views;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.WindowManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -71,15 +76,46 @@
         mThumbnailView.getFocusedRect(r);
     }
 
-    public Rect getFocusedRect() {
+    public Rect getFocusedThumbnailRect() {
         Rect r = new Rect();
-        getFocusedRect(r);
+        mThumbnailView.getGlobalVisibleRect(r);
+        TypedValue out = new TypedValue();
+        getContext().getResources().getValue(R.integer.selected_scale, out, true);
+        float deltaScale = (out.getFloat() - 1.0f) / 2;
+        r.set((int) (r.left - r.left * deltaScale),
+                (int) (r.top - r.top * deltaScale),
+                (int) (r.right + r.right * deltaScale),
+                (int) (r.bottom + r.bottom * deltaScale));
         return r;
     }
 
-    public Rect getGlobalRect() {
-        Rect r = new Rect();
-        getGlobalVisibleRect(r);
-        return r;
+    public static Rect getStartingCardThumbnailRect(Context context) {
+        Resources res = context.getResources();
+
+        TypedValue out = new TypedValue();
+        res.getValue(R.integer.selected_scale, out, true);
+        float scale = out.getFloat();
+
+        int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width);
+        int widthDelta = (int) (width * scale - width);
+        int height = (int) (res.getDimensionPixelOffset(
+                R.dimen.recents_tv_screenshot_height) * scale);
+        int padding = res.getDimensionPixelOffset(R.dimen.recents_tv_grid_row_padding);
+
+        int headerHeight = (int) ((res.getDimensionPixelOffset(
+                R.dimen.recents_tv_card_extra_badge_size) +
+                res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale);
+
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = wm.getDefaultDisplay();
+        Point size = new Point();
+        display.getSize(size);
+        int screenWidth = size.x;
+        int screenHeight = size.y;
+
+        return new Rect(screenWidth - width - padding - widthDelta / 2,
+                screenHeight / 2 - height / 2 + headerHeight / 2,
+                screenWidth - padding + widthDelta / 2,
+                screenHeight / 2 + height / 2 + headerHeight / 2);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 4458639..cf8c9bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -135,7 +135,7 @@
 
     @Override
     public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
-            Task newFrontMostTask, AnimationProps animation) {
+            Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture) {
         getAdapter().notifyItemRemoved(stack.getStackTasks().indexOf(removedTask));
         if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
@@ -144,7 +144,9 @@
         if (mStack.getStackTaskCount() == 0) {
             boolean shouldFinishActivity = (mStack.getStackTaskCount() == 0);
             if (shouldFinishActivity) {
-                EventBus.getDefault().send(new AllTaskViewsDismissedEvent());
+                EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
+                        ? R.string.recents_empty_message
+                        : R.string.recents_empty_message_dismissed_all));
             }
         }
     }
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 8342de5..db97e8f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -97,7 +97,7 @@
     private RecentsAppWidgetHostView mSearchBar;
     private TextView mHistoryButton;
     private TextView mHistoryClearAllButton;
-    private View mEmptyView;
+    private TextView mEmptyView;
     private RecentsHistoryView mHistoryView;
 
     private boolean mAwaitingFirstLayout = true;
@@ -159,7 +159,7 @@
                 }
             });
         }
-        mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
+        mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
         addView(mEmptyView);
 
         setBackground(mBackgroundScrim);
@@ -206,7 +206,7 @@
         if (stack.getTaskCount() > 0) {
             hideEmptyView();
         } else {
-            showEmptyView();
+            showEmptyView(R.string.recents_empty_message);
         }
     }
 
@@ -327,11 +327,12 @@
     /**
      * Hides the task stack and shows the empty view.
      */
-    public void showEmptyView() {
+    public void showEmptyView(int msgResId) {
         if (RecentsDebugFlags.Static.EnableSearchBar && (mSearchBar != null)) {
             mSearchBar.setVisibility(View.INVISIBLE);
         }
         mTaskStackView.setVisibility(View.INVISIBLE);
+        mEmptyView.setText(msgResId);
         mEmptyView.setVisibility(View.VISIBLE);
         mEmptyView.bringToFront();
         if (RecentsDebugFlags.Static.EnableHistory) {
@@ -400,8 +401,8 @@
 
         // Measure the empty view to the full size of the screen
         if (mEmptyView.getVisibility() != GONE) {
-            measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+            measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
         }
 
         if (RecentsDebugFlags.Static.EnableHistory) {
@@ -449,7 +450,13 @@
 
         // Layout the empty view
         if (mEmptyView.getVisibility() != GONE) {
-            mEmptyView.layout(left, top, right, bottom);
+            int leftRightInsets = mSystemInsets.left + mSystemInsets.right;
+            int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
+            int childWidth = mEmptyView.getMeasuredWidth();
+            int childHeight = mEmptyView.getMeasuredHeight();
+            int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
+            int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
+            mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
         }
 
         if (RecentsDebugFlags.Static.EnableHistory) {
@@ -625,7 +632,8 @@
                                     AnimationProps stackAnim = new AnimationProps(
                                             TaskStackView.DEFAULT_SYNC_STACK_DURATION,
                                             Interpolators.FAST_OUT_SLOW_IN);
-                                    mTaskStackView.getStack().removeTask(event.task, stackAnim);
+                                    mTaskStackView.getStack().removeTask(event.task, stackAnim,
+                                            true /* fromDockGesture */);
                                 }
                             }));
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 84590f2..33d5bb7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -150,8 +150,7 @@
         mTaskView.setTranslationY(y);
 
         mVisibleDockStates.clear();
-        if (ActivityManager.supportsMultiWindow() &&
-                !ssp.hasDockedTask() && mRv.getTaskStack().getTaskCount() > 1) {
+        if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()) {
             if (!event.task.isDockable) {
                 Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
                         Toast.LENGTH_SHORT).show();
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 6c410c3..0b20d21 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -61,6 +61,7 @@
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.HideHistoryEvent;
+import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.IterateRecentsEvent;
 import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
@@ -113,6 +114,9 @@
     private static final int DRAG_SCALE_DURATION = 175;
     private static final float DRAG_SCALE_FACTOR = 1.05f;
 
+    private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 200;
+    private static final int LAUNCH_NEXT_SCROLL_INCR_DURATION = 32;
+
     private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();
 
     LayoutInflater mInflater;
@@ -1391,7 +1395,7 @@
      */
     @Override
     public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
-            Task newFrontMostTask, AnimationProps animation) {
+            Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture) {
         if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
         }
@@ -1422,7 +1426,9 @@
 
         // If there are no remaining tasks, then just close recents
         if (mStack.getTaskCount() == 0) {
-            EventBus.getDefault().send(new AllTaskViewsDismissedEvent());
+            EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
+                    ? R.string.recents_empty_message
+                    : R.string.recents_empty_message_dismissed_all));
         }
     }
 
@@ -1595,7 +1601,7 @@
                     tv.dismissTask();
                 } else {
                     // Otherwise, remove the task from the stack immediately
-                    mStack.removeTask(t, AnimationProps.IMMEDIATE);
+                    mStack.removeTask(t, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
                 }
             }
         }
@@ -1618,12 +1624,34 @@
             mUIDozeTrigger.stopDozing();
             cancelAllTaskViewAnimations();
 
-            Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
-            EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
-                    launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+            final Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
+            if (getChildViewForTask(launchTask) == null) {
+                List<TaskView> taskViews = getTaskViews();
+                int lastTaskIndex = !taskViews.isEmpty()
+                        ? mStack.indexOfStackTask(taskViews.get(taskViews.size() - 1).getTask())
+                        : mStack.getTaskCount() - 1;
+                int duration = LAUNCH_NEXT_SCROLL_BASE_DURATION +
+                        Math.abs(mStack.indexOfStackTask(launchTask) - lastTaskIndex)
+                                * LAUNCH_NEXT_SCROLL_INCR_DURATION;
+                mStackScroller.animateScroll(mLayoutAlgorithm.getStackScrollForTask(launchTask),
+                        duration, new Runnable() {
+                            @Override
+                            public void run() {
+                                EventBus.getDefault().send(new LaunchTaskEvent(
+                                        getChildViewForTask(launchTask), launchTask, null,
+                                        INVALID_STACK_ID, false /* screenPinningRequested */));
+                            }
+                        });
+            } else {
+                EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
+                        launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+            }
 
             MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
                     launchTask.key.getComponent().toString());
+        } else if (mStack.getTaskCount() == 0) {
+            // If there are no tasks, then just hide recents back to home.
+            EventBus.getDefault().send(new HideRecentsEvent(false, true));
         }
     }
 
@@ -1911,7 +1939,7 @@
 
         // Remove the task from the stack
         mStack.removeTask(task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
-                Interpolators.FAST_OUT_SLOW_IN));
+                Interpolators.FAST_OUT_SLOW_IN), false /* fromDockGesture */);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index ad46abd..9be3542 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -179,6 +179,13 @@
 
     /** Animates the stack scroll */
     void animateScroll(float newScroll, final Runnable postRunnable) {
+        int duration = mContext.getResources().getInteger(
+                R.integer.recents_animate_task_stack_scroll_duration);
+        animateScroll(newScroll, duration, postRunnable);
+    }
+
+    /** Animates the stack scroll */
+    void animateScroll(float newScroll, int duration, final Runnable postRunnable) {
         // Finish any current scrolling animations
         if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
             setStackScroll(mFinalAnimatedScroll);
@@ -190,8 +197,7 @@
         if (Float.compare(mStackScrollP, newScroll) != 0) {
             mFinalAnimatedScroll = newScroll;
             mScrollAnimator = ObjectAnimator.ofFloat(this, STACK_SCROLL, getStackScroll(), newScroll);
-            mScrollAnimator.setDuration(mContext.getResources().getInteger(
-                    R.integer.recents_animate_task_stack_scroll_duration));
+            mScrollAnimator.setDuration(duration);
             mScrollAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
             mScrollAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index e015666..7f61e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -380,10 +380,9 @@
                     mMoving = true;
                 }
                 if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
-                    int position = calculatePosition(x, y);
-                    SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(position,
-                            0 /* velocity */, false /* hardDismiss */);
-                    resizeStack(calculatePosition(x, y), snapTarget.position, snapTarget);
+                    SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(
+                            mStartPosition, 0 /* velocity */, false /* hardDismiss */);
+                    resizeStack(calculatePosition(x, y), mStartPosition, snapTarget);
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -393,6 +392,13 @@
                 x = (int) event.getRawX();
                 y = (int) event.getRawY();
 
+                if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
+                    int position = calculatePosition(x, y);
+                    SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(position,
+                            0 /* velocity */, false /* hardDismiss */);
+                    resizeStack(calculatePosition(x, y), snapTarget.position, snapTarget);
+                }
+
                 mVelocityTracker.computeCurrentVelocity(1000);
                 int position = calculatePosition(x, y);
                 stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 143f160..bb4a771 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -31,6 +32,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -138,6 +140,8 @@
     protected static final boolean ENABLE_HEADS_UP = true;
     protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
 
+    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
     // Should match the values in PhoneWindowManager
     public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
     public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
@@ -146,6 +150,8 @@
             "com.android.systemui.statusbar.banner_action_cancel";
     private static final String BANNER_ACTION_SETUP =
             "com.android.systemui.statusbar.banner_action_setup";
+    private static final String WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION
+            = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
 
     protected CommandQueue mCommandQueue;
     protected IStatusBarService mBarService;
@@ -199,6 +205,9 @@
     private UserManager mUserManager;
     private int mDensity;
 
+    private KeyguardManager mKeyguardManager;
+    private LockPatternUtils mLockPatternUtils;
+
     // UI-specific methods
 
     /**
@@ -499,6 +508,20 @@
 
                     );
                 }
+            } else if (WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION.equals(action)) {
+                final IntentSender intentSender = (IntentSender) intent
+                        .getParcelableExtra(Intent.EXTRA_INTENT);
+                final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
+                try {
+                    mContext.startIntentSender(intentSender, null, 0, 0, 0);
+                } catch (IntentSender.SendIntentException e) {
+                    /* ignore */
+                }
+                try {
+                    mBarService.onNotificationClick(notificationKey);
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
             }
         }
     };
@@ -661,6 +684,8 @@
         mDensity = currentConfig.densityDpi;
 
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mLockPatternUtils = new LockPatternUtils(mContext);
 
         // Connect in to the status bar manager service
         mCommandQueue = new CommandQueue(this);
@@ -723,10 +748,14 @@
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_PRESENT);
-        filter.addAction(BANNER_ACTION_CANCEL);
-        filter.addAction(BANNER_ACTION_SETUP);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
+        IntentFilter internalFilter = new IntentFilter();
+        internalFilter.addAction(WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
+        internalFilter.addAction(BANNER_ACTION_CANCEL);
+        internalFilter.addAction(BANNER_ACTION_SETUP);
+        mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
+
         IntentFilter allUsersFilter = new IntentFilter();
         allUsersFilter.addAction(
                 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -739,8 +768,7 @@
         if (0 != Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
             Log.d(TAG, "user hasn't seen notification about hidden notifications");
-            final LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
-            if (!lockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+            if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
                 Log.d(TAG, "insecure lockscreen, skipping notification");
                 Settings.Secure.putInt(mContext.getContentResolver(),
                         Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
@@ -1079,6 +1107,7 @@
                         });
                         a.start();
                         guts.setExposed(true);
+                        row.closeRemoteInput();
                         mStackScroller.onHeightChanged(null, true /* needsAnimation */);
                         mNotificationGutsExposed = guts;
                     }
@@ -1680,7 +1709,6 @@
                             ActivityManagerNative.getDefault().resumeAppSwitches();
                         } catch (RemoteException e) {
                         }
-
                         try {
                             intent.send();
                         } catch (PendingIntent.CanceledException e) {
@@ -1773,8 +1801,22 @@
                                 ActivityManagerNative.getDefault().resumeAppSwitches();
                             } catch (RemoteException e) {
                             }
-
                             if (intent != null) {
+                                // If we are launching a work activity and require to launch
+                                // separate work challenge, we defer the activity action and cancel
+                                // notification until work challenge is unlocked.
+                                if (intent.isActivity()) {
+                                    final int userId = intent.getCreatorUserHandle()
+                                            .getIdentifier();
+                                    if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+                                            && mKeyguardManager.isDeviceLocked(userId)) {
+                                        // Show work challenge, do not run pendingintent and
+                                        // remove notification
+                                        startWorkChallenge(userId, intent.getIntentSender(),
+                                                notificationKey);
+                                        return;
+                                    }
+                                }
                                 try {
                                     intent.send();
                                 } catch (PendingIntent.CanceledException e) {
@@ -1809,6 +1851,23 @@
             }, afterKeyguardGone);
         }
 
+        public void startWorkChallenge(int userId, IntentSender intendSender,
+                String notificationKey) {
+            final Intent callBackIntent = new Intent(
+                    WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
+            callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
+            callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
+            callBackIntent.setPackage(mContext.getPackageName());
+
+            final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+                    null, userId);
+            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+            newIntent.putExtra(Intent.EXTRA_INTENT, PendingIntent
+                    .getBroadcast(mContext, 0, callBackIntent, 0).getIntentSender());
+            mContext.startActivity(newIntent);
+        }
+
         public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
             Notification notification = sbn.getNotification();
             if (notification.contentIntent != null || notification.fullScreenIntent != null) {
@@ -1856,15 +1915,16 @@
 
     /**
      * The LEDs are turned off when the notification panel is shown, even just a little bit.
+     * See also NotificationStackScrollLayout.setIsExpanded() for another place where we
+     * attempt to do this.
      */
     protected void handleVisibleToUserChanged(boolean visibleToUser) {
         try {
             if (visibleToUser) {
                 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
                 boolean clearNotificationEffects =
-                    ((mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD) ||
-                            (!pinnedHeadsUp && (mState == StatusBarState.SHADE
-                                    || mState == StatusBarState.SHADE_LOCKED)));
+                        !isPanelFullyCollapsed() &&
+                        (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
                 int notificationLoad = mNotificationData.getActiveNotifications().size();
                 if (pinnedHeadsUp && isPanelFullyCollapsed())  {
                     notificationLoad = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 246f15e..22bb8eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -579,6 +579,11 @@
         }
     }
 
+    public void closeRemoteInput() {
+        mPrivateLayout.closeRemoteInput();
+        mPublicLayout.closeRemoteInput();
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutKeysLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutKeysLayout.java
new file mode 100644
index 0000000..ba3e774
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutKeysLayout.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Layout used as a container for keyboard shortcut keys. It's children are wrapped and right
+ * aligned.
+ */
+public final class KeyboardShortcutKeysLayout extends ViewGroup {
+    private int mLineHeight;
+
+    public KeyboardShortcutKeysLayout(Context context) {
+        super(context);
+    }
+
+    public KeyboardShortcutKeysLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
+        int childCount = getChildCount();
+        int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
+        int lineHeight = 0;
+        int xPos = getPaddingLeft();
+        int yPos = getPaddingTop();
+
+        int childHeightMeasureSpec;
+        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
+        } else {
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        }
+
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
+                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+                        childHeightMeasureSpec);
+                int childWidth = child.getMeasuredWidth();
+                lineHeight = Math.max(lineHeight,
+                        child.getMeasuredHeight() + layoutParams.mVerticalSpacing);
+
+                if (xPos + childWidth > width) {
+                    xPos = getPaddingLeft();
+                    yPos += lineHeight;
+                }
+                xPos += childWidth + layoutParams.mHorizontalSpacing;
+            }
+        }
+        this.mLineHeight = lineHeight;
+
+        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
+            height = yPos + lineHeight;
+        } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+            if (yPos + lineHeight < height) {
+                height = yPos + lineHeight;
+            }
+        }
+        setMeasuredDimension(width, height);
+    }
+
+    @Override
+    protected LayoutParams generateDefaultLayoutParams() {
+        int spacing = getHorizontalVerticalSpacing();
+        return new LayoutParams(spacing, spacing);
+    }
+
+    @Override
+    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams layoutParams) {
+        int spacing = getHorizontalVerticalSpacing();
+        return new LayoutParams(spacing, spacing, layoutParams);
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return (p instanceof LayoutParams);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int childCount = getChildCount();
+        int fullRowWidth = r - l;
+        int xPos = getPaddingLeft();
+        int yPos = getPaddingTop();
+        int lastHorizontalSpacing = 0;
+        // The index of the child which starts the current row.
+        int rowStartIdx = 0;
+
+        // Go through all the children.
+        for (int i = 0; i < childCount; i++) {
+            View currentChild = getChildAt(i);
+            if (currentChild.getVisibility() != GONE) {
+                int currentChildWidth = currentChild.getMeasuredWidth();
+                LayoutParams lp = (LayoutParams) currentChild.getLayoutParams();
+
+                // If the current child does not fit on this row.
+                if (xPos + currentChildWidth > fullRowWidth) {
+                    // Layout all the children on this row but the current one.
+                    layoutChildrenOnRow(rowStartIdx, i, fullRowWidth, xPos, yPos,
+                            lastHorizontalSpacing);
+                    // Update the positions for starting on the new row.
+                    xPos = getPaddingLeft();
+                    yPos += mLineHeight;
+                    rowStartIdx = i;
+                }
+
+                xPos += currentChildWidth + lp.mHorizontalSpacing;
+                lastHorizontalSpacing = lp.mHorizontalSpacing;
+            }
+        }
+
+        // Lay out the children on the last row.
+        if (rowStartIdx < childCount) {
+            layoutChildrenOnRow(rowStartIdx, childCount, fullRowWidth, xPos, yPos,
+                    lastHorizontalSpacing);
+        }
+    }
+
+    private int getHorizontalVerticalSpacing() {
+        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+        return (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, 4, displayMetrics);
+    }
+
+    private void layoutChildrenOnRow(int startIndex, int endIndex, int fullRowWidth, int xPos,
+            int yPos, int lastHorizontalSpacing) {
+        int freeSpace = fullRowWidth - xPos + lastHorizontalSpacing;
+        xPos = getPaddingLeft() + freeSpace;
+
+        for (int j = startIndex; j < endIndex; ++j) {
+            View currentChild = getChildAt(j);
+            currentChild.layout(
+                    xPos,
+                    yPos,
+                    xPos + currentChild.getMeasuredWidth(),
+                    yPos + currentChild.getMeasuredHeight());
+            xPos += currentChild.getMeasuredWidth()
+                    + ((LayoutParams) currentChild.getLayoutParams()).mHorizontalSpacing;
+        }
+    }
+
+    public static class LayoutParams extends ViewGroup.LayoutParams {
+        public final int mHorizontalSpacing;
+        public final int mVerticalSpacing;
+
+        public LayoutParams(int horizontalSpacing, int verticalSpacing,
+                ViewGroup.LayoutParams viewGroupLayout) {
+            super(viewGroupLayout);
+            this.mHorizontalSpacing = horizontalSpacing;
+            this.mVerticalSpacing = verticalSpacing;
+        }
+
+        public LayoutParams(int mHorizontalSpacing, int verticalSpacing) {
+            super(0, 0);
+            this.mHorizontalSpacing = mHorizontalSpacing;
+            this.mVerticalSpacing = verticalSpacing;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 0b7bfa8..60c2fa6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -29,6 +29,7 @@
 import android.view.KeyboardShortcutInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
 import android.widget.LinearLayout;
@@ -153,7 +154,7 @@
                         .findViewById(R.id.keyboard_shortcuts_keyword);
                 textView.setText(info.getLabel());
 
-                LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView
+                ViewGroup shortcutItemsContainer = (ViewGroup) shortcutView
                         .findViewById(R.id.keyboard_shortcuts_item_container);
                 List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
                 final int shortcutKeysSize = shortcutKeys.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 3b87577..c2df292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -69,6 +69,9 @@
     private View mHeadsUpChild;
     private HybridNotificationView mSingleLineView;
 
+    private RemoteInputView mExpandedRemoteInput;
+    private RemoteInputView mHeadsUpRemoteInput;
+
     private NotificationViewWrapper mContractedWrapper;
     private NotificationViewWrapper mExpandedWrapper;
     private NotificationViewWrapper mHeadsUpWrapper;
@@ -743,15 +746,19 @@
 
         View bigContentView = mExpandedChild;
         if (bigContentView != null) {
-            applyRemoteInput(bigContentView, entry, hasRemoteInput);
+            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput);
+        } else {
+            mExpandedRemoteInput = null;
         }
         View headsUpContentView = mHeadsUpChild;
         if (headsUpContentView != null) {
-            applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
+            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
+        } else {
+            mHeadsUpRemoteInput = null;
         }
     }
 
-    private void applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
+    private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
         View actionContainerCandidate = view.findViewById(
                 com.android.internal.R.id.actions_container);
         if (actionContainerCandidate instanceof FrameLayout) {
@@ -777,7 +784,20 @@
                     color = mContext.getColor(R.color.default_remote_input_background);
                 }
                 riv.setBackgroundColor(color);
+
+                return riv;
             }
+            return existing;
+        }
+        return null;
+    }
+
+    public void closeRemoteInput() {
+        if (mHeadsUpRemoteInput != null) {
+            mHeadsUpRemoteInput.close();
+        }
+        if (mExpandedRemoteInput != null) {
+            mExpandedRemoteInput.close();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index e53f044..99896f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -36,7 +36,6 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Display;
-import android.view.Gravity;
 import android.view.IDockedStackListener.Stub;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -46,7 +45,6 @@
 import android.view.WindowManagerGlobal;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.LinearLayout;
-
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.stackdivider.Divider;
@@ -54,7 +52,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 
 public class NavigationBarView extends LinearLayout {
     final static boolean DEBUG = false;
@@ -100,6 +97,7 @@
     private boolean mDockedStackExists;
 
     private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
+    private int mDensity;
 
     private class NavTransitionListener implements TransitionListener {
         private boolean mBackTransitioning;
@@ -190,6 +188,7 @@
         mShowMenu = false;
         mGestureHelper = new NavigationBarGestureHelper(context);
 
+        mDensity = context.getResources().getConfiguration().densityDpi;
         getIcons(context);
 
         mBarTransitions = new NavigationBarTransitions(this);
@@ -599,6 +598,10 @@
             // we are switching to.
             setNavigationIconHints(mNavigationIconHints, true);
         }
+        if (mDensity != newConfig.densityDpi) {
+            mDensity = newConfig.densityDpi;
+            getIcons(getContext());
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index eb5b57e..95f26d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -16,24 +16,42 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
 import android.app.StatusBarManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.media.session.MediaSessionLegacyHelper;
+import android.net.Uri;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.util.AttributeSet;
+import android.view.ActionMode;
+import android.view.InputQueue;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.SurfaceHolder;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.widget.FrameLayout;
 
+import com.android.internal.view.FloatingActionMode;
+import com.android.internal.widget.FloatingToolbar;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -57,6 +75,13 @@
     private final Paint mTransparentSrcPaint = new Paint();
     private FalsingManager mFalsingManager;
 
+    // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
+    // DecorView, but since this is a special window we have to roll our own.
+    private View mFloatingActionModeOriginatingView;
+    private ActionMode mFloatingActionMode;
+    private FloatingToolbar mFloatingToolbar;
+    private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
+
     public StatusBarWindowView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setMotionEventSplittingEnabled(false);
@@ -301,5 +326,341 @@
             a.recycle();
         }
     }
+
+    @Override
+    public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
+            int type) {
+        if (type == ActionMode.TYPE_FLOATING) {
+            return startActionMode(originalView, callback, type);
+        }
+        return super.startActionModeForChild(originalView, callback, type);
+    }
+
+    private ActionMode createFloatingActionMode(
+            View originatingView, ActionMode.Callback2 callback) {
+        if (mFloatingActionMode != null) {
+            mFloatingActionMode.finish();
+        }
+        cleanupFloatingActionModeViews();
+        final FloatingActionMode mode =
+                new FloatingActionMode(mContext, callback, originatingView);
+        mFloatingActionModeOriginatingView = originatingView;
+        mFloatingToolbarPreDrawListener =
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        mode.updateViewLocationInWindow();
+                        return true;
+                    }
+                };
+        return mode;
+    }
+
+    private void setHandledFloatingActionMode(ActionMode mode) {
+        mFloatingActionMode = mode;
+        mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow);
+        ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
+        mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
+        mFloatingActionModeOriginatingView.getViewTreeObserver()
+                .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
+    }
+
+    private void cleanupFloatingActionModeViews() {
+        if (mFloatingToolbar != null) {
+            mFloatingToolbar.dismiss();
+            mFloatingToolbar = null;
+        }
+        if (mFloatingActionModeOriginatingView != null) {
+            if (mFloatingToolbarPreDrawListener != null) {
+                mFloatingActionModeOriginatingView.getViewTreeObserver()
+                        .removeOnPreDrawListener(mFloatingToolbarPreDrawListener);
+                mFloatingToolbarPreDrawListener = null;
+            }
+            mFloatingActionModeOriginatingView = null;
+        }
+    }
+
+    private ActionMode startActionMode(
+            View originatingView, ActionMode.Callback callback, int type) {
+        ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
+        ActionMode mode = createFloatingActionMode(originatingView, wrappedCallback);
+        if (mode != null && wrappedCallback.onCreateActionMode(mode, mode.getMenu())) {
+            setHandledFloatingActionMode(mode);
+        } else {
+            mode = null;
+        }
+        return mode;
+    }
+
+    private class ActionModeCallback2Wrapper extends ActionMode.Callback2 {
+        private final ActionMode.Callback mWrapped;
+
+        public ActionModeCallback2Wrapper(ActionMode.Callback wrapped) {
+            mWrapped = wrapped;
+        }
+
+        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            return mWrapped.onCreateActionMode(mode, menu);
+        }
+
+        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+            requestFitSystemWindows();
+            return mWrapped.onPrepareActionMode(mode, menu);
+        }
+
+        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            return mWrapped.onActionItemClicked(mode, item);
+        }
+
+        public void onDestroyActionMode(ActionMode mode) {
+            mWrapped.onDestroyActionMode(mode);
+            if (mode == mFloatingActionMode) {
+                cleanupFloatingActionModeViews();
+                mFloatingActionMode = null;
+            }
+            requestFitSystemWindows();
+        }
+
+        @Override
+        public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+            if (mWrapped instanceof ActionMode.Callback2) {
+                ((ActionMode.Callback2) mWrapped).onGetContentRect(mode, view, outRect);
+            } else {
+                super.onGetContentRect(mode, view, outRect);
+            }
+        }
+    }
+
+    /**
+     * Minimal window to satisfy FloatingToolbar.
+     */
+    private Window mFakeWindow = new Window(mContext) {
+        @Override
+        public void takeSurface(SurfaceHolder.Callback2 callback) {
+        }
+
+        @Override
+        public void takeInputQueue(InputQueue.Callback callback) {
+        }
+
+        @Override
+        public boolean isFloating() {
+            return false;
+        }
+
+        @Override
+        public void alwaysReadCloseOnTouchAttr() {
+        }
+
+        @Override
+        public void setContentView(@LayoutRes int layoutResID) {
+        }
+
+        @Override
+        public void setContentView(View view) {
+        }
+
+        @Override
+        public void setContentView(View view, ViewGroup.LayoutParams params) {
+        }
+
+        @Override
+        public void addContentView(View view, ViewGroup.LayoutParams params) {
+        }
+
+        @Override
+        public void clearContentView() {
+        }
+
+        @Override
+        public View getCurrentFocus() {
+            return null;
+        }
+
+        @Override
+        public LayoutInflater getLayoutInflater() {
+            return null;
+        }
+
+        @Override
+        public void setTitle(CharSequence title) {
+        }
+
+        @Override
+        public void setTitleColor(@ColorInt int textColor) {
+        }
+
+        @Override
+        public void openPanel(int featureId, KeyEvent event) {
+        }
+
+        @Override
+        public void closePanel(int featureId) {
+        }
+
+        @Override
+        public void togglePanel(int featureId, KeyEvent event) {
+        }
+
+        @Override
+        public void invalidatePanelMenu(int featureId) {
+        }
+
+        @Override
+        public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
+            return false;
+        }
+
+        @Override
+        public boolean performPanelIdentifierAction(int featureId, int id, int flags) {
+            return false;
+        }
+
+        @Override
+        public void closeAllPanels() {
+        }
+
+        @Override
+        public boolean performContextMenuIdentifierAction(int id, int flags) {
+            return false;
+        }
+
+        @Override
+        public void onConfigurationChanged(Configuration newConfig) {
+        }
+
+        @Override
+        public void setBackgroundDrawable(Drawable drawable) {
+        }
+
+        @Override
+        public void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
+        }
+
+        @Override
+        public void setFeatureDrawableUri(int featureId, Uri uri) {
+        }
+
+        @Override
+        public void setFeatureDrawable(int featureId, Drawable drawable) {
+        }
+
+        @Override
+        public void setFeatureDrawableAlpha(int featureId, int alpha) {
+        }
+
+        @Override
+        public void setFeatureInt(int featureId, int value) {
+        }
+
+        @Override
+        public void takeKeyEvents(boolean get) {
+        }
+
+        @Override
+        public boolean superDispatchKeyEvent(KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchTouchEvent(MotionEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchTrackballEvent(MotionEvent event) {
+            return false;
+        }
+
+        @Override
+        public boolean superDispatchGenericMotionEvent(MotionEvent event) {
+            return false;
+        }
+
+        @Override
+        public View getDecorView() {
+            return StatusBarWindowView.this;
+        }
+
+        @Override
+        public View peekDecorView() {
+            return null;
+        }
+
+        @Override
+        public Bundle saveHierarchyState() {
+            return null;
+        }
+
+        @Override
+        public void restoreHierarchyState(Bundle savedInstanceState) {
+        }
+
+        @Override
+        protected void onActive() {
+        }
+
+        @Override
+        public void setChildDrawable(int featureId, Drawable drawable) {
+        }
+
+        @Override
+        public void setChildInt(int featureId, int value) {
+        }
+
+        @Override
+        public boolean isShortcutKey(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        @Override
+        public void setVolumeControlStream(int streamType) {
+        }
+
+        @Override
+        public int getVolumeControlStream() {
+            return 0;
+        }
+
+        @Override
+        public int getStatusBarColor() {
+            return 0;
+        }
+
+        @Override
+        public void setStatusBarColor(@ColorInt int color) {
+        }
+
+        @Override
+        public int getNavigationBarColor() {
+            return 0;
+        }
+
+        @Override
+        public void setNavigationBarColor(@ColorInt int color) {
+        }
+
+        @Override
+        public void setDecorCaptionShade(int decorCaptionShade) {
+        }
+
+        @Override
+        public void setResizingCaptionDrawable(Drawable drawable) {
+        }
+
+        @Override
+        public void onMultiWindowChanged() {
+        }
+
+        @Override
+        public void reportActivityRelaunched() {
+        }
+    };
+
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index f03d9e9..c6b1cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -69,18 +69,22 @@
 
     @Override
     public void addCallback(Callback callback) {
-        if (callback == null || mCallbacks.contains(callback)) return;
-        if (DEBUG) Log.d(TAG, "addCallback " + callback);
-        mCallbacks.add(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        synchronized (mCallbacks) {
+            if (callback == null || mCallbacks.contains(callback)) return;
+            if (DEBUG) Log.d(TAG, "addCallback " + callback);
+            mCallbacks.add(callback);
+            mReceiver.setListening(!mCallbacks.isEmpty());
+        }
     }
 
     @Override
     public void removeCallback(Callback callback) {
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
-        mCallbacks.remove(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
+            mReceiver.setListening(!mCallbacks.isEmpty());
+        }
     }
 
     @Override
@@ -110,8 +114,10 @@
     }
 
     private void fireCallback(boolean isEnabled) {
-        for (Callback callback : mCallbacks) {
-            callback.onHotspotChanged(isEnabled);
+        synchronized (mCallbacks) {
+            for (Callback callback : mCallbacks) {
+                callback.onHotspotChanged(isEnabled);
+            }
         }
     }
 
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 29b0f4b..3a0336b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -29,8 +29,10 @@
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -44,6 +46,7 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.stack.LongPressCancelable;
 
 /**
  * Host for the remote input.
@@ -64,6 +67,7 @@
     private RemoteInputController mController;
 
     private NotificationData.Entry mEntry;
+    private LongPressCancelable mLongPressCancelable;
 
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -226,6 +230,30 @@
         updateSendButton();
     }
 
+    public void close() {
+        mEditText.defocusIfNeeded();
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (mLongPressCancelable == null) {
+                ViewParent p = getParent();
+                while (p != null) {
+                    if (p instanceof LongPressCancelable) {
+                        mLongPressCancelable = (LongPressCancelable) p;
+                        break;
+                    }
+                    p = p.getParent();
+                }
+            }
+            if (mLongPressCancelable != null) {
+                mLongPressCancelable.requestDisallowLongPress();
+            }
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
     /**
      * An EditText that changes appearance based on whether it's focusable and becomes
      * un-focusable whenever the user navigates away from it or it becomes invisible.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
new file mode 100644
index 0000000..05f0c07
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.stack;
+
+/**
+ * Interface for container layouts that listen for long presses. A child that
+ * wants to handle long press can use this to cancel the parents long press logic.
+ */
+public interface LongPressCancelable {
+    /**
+     * Request that the view does not perform long press for the current touch.
+     */
+    void requestDisallowLongPress();
+}
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 d9b78a2..686a712 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -83,7 +83,7 @@
 public class NotificationStackScrollLayout extends ViewGroup
         implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
         ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
-        SettingsIconRowListener {
+        SettingsIconRowListener, LongPressCancelable {
 
     public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
     private static final String TAG = "StackScroller";
@@ -2627,6 +2627,11 @@
         }
     }
 
+    @Override
+    public void requestDisallowLongPress() {
+        removeLongPressCallback();
+    }
+
     public void removeLongPressCallback() {
         mSwipeHelper.removeLongPressCallback();
     }
@@ -2691,6 +2696,16 @@
         if (changed) {
             if (!mIsExpanded) {
                 mGroupManager.collapseAllGroups();
+            } else {
+                // XXX: HACK: we should not be clearing notification effects from way down here.
+                // But at the moment we don't have a reliable way to know when the window is
+                // actually exposed to the air, so
+                if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+                    if (DEBUG) {
+                        Log.v(TAG, "clearing notification effects from scroller");
+                    }
+                    mPhoneStatusBar.clearNotificationEffects();
+                }
             }
             updateNotificationAnimationStates();
             updateChronometers();
diff --git a/packages/services/Proxy/AndroidManifest.xml b/packages/services/Proxy/AndroidManifest.xml
index 88f8381..51531e3 100644
--- a/packages/services/Proxy/AndroidManifest.xml
+++ b/packages/services/Proxy/AndroidManifest.xml
@@ -8,8 +8,8 @@
     <application
         android:label="@string/app_label"
         android:process="com.android.proxyhandler"
-        android:forceDeviceEncrypted="true"
-        android:encryptionAware="true">
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true">
 
         <service android:name=".ProxyService"
             android:exported="true">
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index b4b40ae..9ce81ed 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -56,6 +56,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -174,6 +175,8 @@
 
     private final PackageManager mPackageManager;
 
+    private final PowerManager mPowerManager;
+
     private final WindowManagerInternal mWindowManagerService;
 
     private final SecurityPolicy mSecurityPolicy;
@@ -232,6 +235,7 @@
     public AccessibilityManagerService(Context context) {
         mContext = context;
         mPackageManager = mContext.getPackageManager();
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mSecurityPolicy = new SecurityPolicy();
@@ -1013,7 +1017,8 @@
                 PackageManager.GET_SERVICES
                         | PackageManager.GET_META_DATA
                         | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
-                        | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                 mCurrentUserId);
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -1801,7 +1806,8 @@
     private KeyEventDispatcher getKeyEventDispatcher() {
         if (mKeyEventDispatcher == null) {
             mKeyEventDispatcher = new KeyEventDispatcher(
-                    mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock);
+                    mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock,
+                    mPowerManager);
         }
         return mKeyEventDispatcher;
     }
@@ -2702,6 +2708,11 @@
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
             try {
+                // Regardless of whether or not the action succeeds, it was generated by an
+                // accessibility service that is driven by user actions, so note user activity.
+                mPowerManager.userActivity(SystemClock.uptimeMillis(),
+                        PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
+
                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
             } catch (RemoteException re) {
@@ -2723,6 +2734,8 @@
             }
             final long identity = Binder.clearCallingIdentity();
             try {
+                mPowerManager.userActivity(SystemClock.uptimeMillis(),
+                        PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
                 switch (action) {
                     case AccessibilityService.GLOBAL_ACTION_BACK: {
                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
diff --git a/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
index 3469565..e03c16e 100644
--- a/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
+++ b/services/accessibility/java/com/android/server/accessibility/KeyEventDispatcher.java
@@ -17,8 +17,10 @@
 package com.android.server.accessibility;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Pools;
@@ -69,6 +71,7 @@
     private final Handler mHandlerToSendKeyEventsToInputFilter;
     private final int mMessageTypeForSendKeyEvent;
     private final Handler mKeyEventTimeoutHandler;
+    private final PowerManager mPowerManager;
 
     /**
      * @param handlerToSendKeyEventsToInputFilter The handler to which to post {@code KeyEvent}s
@@ -77,9 +80,12 @@
      * message that carries a {@code KeyEvent} to be sent to the input filter
      * @param lock The lock used for all synchronization in this package. This lock must be held
      * when calling {@code notifyKeyEventLocked}
+     * @param powerManager The power manager to alert to user activity if a KeyEvent is processed
+     * by a service
      */
     public KeyEventDispatcher(Handler handlerToSendKeyEventsToInputFilter,
-                              int messageTypeForSendKeyEvent, Object lock) {
+            int messageTypeForSendKeyEvent, Object lock,
+            PowerManager powerManager) {
         if (InputEventConsistencyVerifier.isInstrumentationEnabled()) {
             mSentEventsVerifier = new InputEventConsistencyVerifier(
                     this, 0, KeyEventDispatcher.class.getSimpleName());
@@ -91,6 +97,7 @@
         mKeyEventTimeoutHandler =
                 new Handler(mHandlerToSendKeyEventsToInputFilter.getLooper(), new Callback());
         mLock = lock;
+        mPowerManager = powerManager;
     }
 
     /**
@@ -165,7 +172,16 @@
             PendingKeyEvent pendingEvent =
                     removeEventFromListLocked(mPendingEventsMap.get(service), sequence);
             if (pendingEvent != null) {
-                pendingEvent.handled |= handled;
+                if (handled && !pendingEvent.handled) {
+                    pendingEvent.handled = handled;
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        mPowerManager.userActivity(pendingEvent.event.getEventTime(),
+                                PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+                }
                 removeReferenceToPendingEventLocked(pendingEvent);
             }
         }
@@ -241,7 +257,7 @@
             int policyFlags = pendingEvent.policyFlags | WindowManagerPolicy.FLAG_PASS_TO_USER;
             mHandlerToSendKeyEventsToInputFilter
                     .obtainMessage(mMessageTypeForSendKeyEvent, policyFlags, 0, pendingEvent.event)
-                            .sendToTarget();
+                    .sendToTarget();
         } else {
             pendingEvent.event.recycle();
         }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index a4f85db..8febecc 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2487,7 +2487,8 @@
             // from a profile that is still locked, so let them see those
             // widgets.
             if (isProfileWithUnlockedParent(userId)) {
-                flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+                flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
             }
 
             // Widgets referencing shared libraries need to have their
diff --git a/services/core/Android.mk b/services/core/Android.mk
index aaa2211..99c5dd6 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -7,7 +7,8 @@
 LOCAL_SRC_FILES += \
     $(call all-java-files-under,java) \
     java/com/android/server/EventLogTags.logtags \
-    java/com/android/server/am/EventLogTags.logtags
+    java/com/android/server/am/EventLogTags.logtags \
+    ../../../../system/netd/server/binder/android/net/INetd.aidl
 
 LOCAL_JAVA_LIBRARIES := services.net telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index bfe9e8e..a94c8b8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -121,6 +121,8 @@
      *       - SparseArray w/ mapping:
      *          AppOp code --> Set of packages that are not restricted for this code
      *
+     * For efficiency, a core assumption here is that the number of per-package exemptions stored
+     * here will be relatively small.  If this changes, this data structure should be revisited.
      */
     private final ArrayMap<IBinder, SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>>>
             mOpUserRestrictions = new ArrayMap<>();
@@ -445,8 +447,12 @@
             int[] ops) {
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return Collections.emptyList();
+        }
         synchronized (this) {
-            Ops pkgOps = getOpsLocked(uid, packageName, false);
+            Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false);
             if (pkgOps == null) {
                 return null;
             }
@@ -464,7 +470,7 @@
 
     private void pruneOp(Op op, int uid, String packageName) {
         if (op.time == 0 && op.rejectTime == 0) {
-            Ops ops = getOpsLocked(uid, packageName, false);
+            Ops ops = getOpsRawLocked(uid, packageName, false);
             if (ops != null) {
                 ops.remove(op.op);
                 if (ops.size() <= 0) {
@@ -878,8 +884,12 @@
     public int checkOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
         synchronized (this) {
-            if (isOpRestricted(uid, code, packageName)) {
+            if (isOpRestricted(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             code = AppOpsManager.opToSwitch(code);
@@ -890,7 +900,7 @@
                     return uidMode;
                 }
             }
-            Op op = getOpLocked(code, uid, packageName, false);
+            Op op = getOpLocked(code, uid, resolvedPackageName, false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
@@ -966,6 +976,7 @@
 
     @Override
     public int checkPackage(int uid, String packageName) {
+        Preconditions.checkNotNull(packageName);
         synchronized (this) {
             if (getOpsRawLocked(uid, packageName, true) != null) {
                 return AppOpsManager.MODE_ALLOWED;
@@ -979,26 +990,39 @@
     public int noteProxyOperation(int code, String proxyPackageName,
             int proxiedUid, String proxiedPackageName) {
         verifyIncomingOp(code);
-        final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
-                proxyPackageName, -1, null);
+        final int proxyUid = Binder.getCallingUid();
+        String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
+        if (resolveProxyPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        final int proxyMode = noteOperationUnchecked(code, proxyUid,
+                resolveProxyPackageName, -1, null);
         if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
             return proxyMode;
         }
-        return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
-                Binder.getCallingUid(), proxyPackageName);
+        String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
+        if (resolveProxiedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
+                proxyMode, resolveProxyPackageName);
     }
 
     @Override
     public int noteOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        return noteOperationUnchecked(code, uid, packageName, 0, null);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
     }
 
     private int noteOperationUnchecked(int code, int uid, String packageName,
             int proxyUid, String proxyPackageName) {
         synchronized (this) {
-            Ops ops = getOpsLocked(uid, packageName, true);
+            Ops ops = getOpsRawLocked(uid, packageName, true);
             if (ops == null) {
                 if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
@@ -1046,16 +1070,20 @@
     public int startOperation(IBinder token, int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return  AppOpsManager.MODE_IGNORED;
+        }
         ClientState client = (ClientState)token;
         synchronized (this) {
-            Ops ops = getOpsLocked(uid, packageName, true);
+            Ops ops = getOpsRawLocked(uid, resolvedPackageName, true);
             if (ops == null) {
                 if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
-                        + " package " + packageName);
+                        + " package " + resolvedPackageName);
                 return AppOpsManager.MODE_ERRORED;
             }
             Op op = getOpLocked(ops, code, true);
-            if (isOpRestricted(uid, code, packageName)) {
+            if (isOpRestricted(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1065,7 +1093,7 @@
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
-                            + packageName);
+                            + resolvedPackageName);
                     op.rejectTime = System.currentTimeMillis();
                     return uidMode;
                 }
@@ -1073,12 +1101,13 @@
             final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
             if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
                 if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
-                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
+                        + switchCode + " (" + code + ") uid " + uid + " package "
+                        + resolvedPackageName);
                 op.rejectTime = System.currentTimeMillis();
                 return switchOp.mode;
             }
             if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
-                    + " package " + packageName);
+                    + " package " + resolvedPackageName);
             if (op.nesting == 0) {
                 op.time = System.currentTimeMillis();
                 op.rejectTime = 0;
@@ -1096,9 +1125,16 @@
     public void finishOperation(IBinder token, int code, int uid, String packageName) {
         verifyIncomingUid(uid);
         verifyIncomingOp(code);
-        ClientState client = (ClientState)token;
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return;
+        }
+        if (!(token instanceof ClientState)) {
+            return;
+        }
+        ClientState client = (ClientState) token;
         synchronized (this) {
-            Op op = getOpLocked(code, uid, packageName, true);
+            Op op = getOpLocked(code, uid, resolvedPackageName, true);
             if (op == null) {
                 return;
             }
@@ -1114,6 +1150,9 @@
 
     @Override
     public int permissionToOpCode(String permission) {
+        if (permission == null) {
+            return AppOpsManager.OP_NONE;
+        }
         return AppOpsManager.permissionToOpCode(permission);
     }
 
@@ -1163,15 +1202,6 @@
         return uidState;
     }
 
-    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
-        if (uid == 0) {
-            packageName = "root";
-        } else if (uid == Process.SHELL_UID) {
-            packageName = "com.android.shell";
-        }
-        return getOpsRawLocked(uid, packageName, edit);
-    }
-
     private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
         UidState uidState = getUidStateLocked(uid, edit);
         if (uidState == null) {
@@ -1257,7 +1287,7 @@
     }
 
     private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
-        Ops ops = getOpsLocked(uid, packageName, edit);
+        Ops ops = getOpsRawLocked(uid, packageName, edit);
         if (ops == null) {
             return null;
         }
@@ -1304,15 +1334,18 @@
             }
 
             if (opRestrictions[code]) {
-                if (opExceptions != null && opExceptions.get(code) != null &&
-                        opExceptions.get(code).contains(packageName)) {
-                    continue; // AppOps code is restricted, but this package is exempt
+
+                if (opExceptions != null) {
+                    ArraySet<String> ex = opExceptions.get(code);
+                    if (ex != null && ex.contains(packageName)) {
+                        continue; // AppOps code is restricted, but this package is exempt
+                    }
                 }
 
                 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
                     // If we are the system, bypass user restrictions for certain codes
                     synchronized (this) {
-                        Ops ops = getOpsLocked(uid, packageName, true);
+                        Ops ops = getOpsRawLocked(uid, packageName, true);
                         if ((ops != null) && ops.isPrivileged) {
                             return false;
                         }
@@ -1577,7 +1610,7 @@
                         out.startTag(null, "uid");
                         out.attribute(null, "n", Integer.toString(pkg.getUid()));
                         synchronized (this) {
-                            Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false);
+                            Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false);
                             // Should always be present as the list of PackageOps is generated
                             // from Ops.
                             if (ops != null) {
@@ -2098,6 +2131,7 @@
     @Override
     public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
         checkSystemUid("setUserRestrictions");
+        Preconditions.checkNotNull(restrictions);
         Preconditions.checkNotNull(token);
         final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
         for (int i = 0; i < opRestrictions.length; ++i) {
@@ -2143,9 +2177,8 @@
             final SparseArray<ArraySet<String>> opExceptions =
                     getUserPackageExemptionsForToken(token, userHandle);
 
-            // If exceptionPackages is not null, update the exception packages for this AppOps code
             ArraySet<String> exceptions = opExceptions.get(code);
-            if (exceptionPackages != null) {
+            if (exceptionPackages != null && exceptionPackages.length > 0) {
                 if (exceptions == null) {
                     exceptions = new ArraySet<>(exceptionPackages.length);
                     opExceptions.put(code, exceptions);
@@ -2153,7 +2186,11 @@
                     exceptions.clear();
                 }
 
-                exceptions.addAll(Arrays.asList(exceptionPackages));
+                for (String p : exceptionPackages) {
+                    exceptions.add(p);
+                }
+            } else {
+                opExceptions.remove(code);
             }
         }
 
@@ -2219,14 +2256,23 @@
 
             if (restrictions != null) {
                 final boolean[] opRestrictions = restrictions.first;
+                final SparseArray<ArraySet<String>> opExceptions = restrictions.second;
+                boolean stillHasRestrictions = false;
                 if (opRestrictions != null) {
-                    for (boolean restriction : opRestrictions) {
+                    for (int i = 0; i < opRestrictions.length; i++) {
+                        boolean restriction = opRestrictions[i];
                         if (restriction) {
-                            return;
+                            stillHasRestrictions = true;
+                        } else {
+                            opExceptions.remove(i);
                         }
                     }
                 }
 
+                if (stillHasRestrictions) {
+                    return;
+                }
+
                 // No restrictions set for this client
                 perTokenRestrictions.remove(userHandle);
                 if (perTokenRestrictions.size() <= 0) {
@@ -2300,6 +2346,15 @@
         }
     }
 
+    private static String resolvePackageName(int uid, String packageName)  {
+        if (uid == 0) {
+            return "root";
+        } else if (uid == Process.SHELL_UID) {
+            return "com.android.shell";
+        }
+        return packageName;
+    }
+
     private static String[] getPackagesForUid(int uid) {
         String[] packageNames = null;
         try {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 9b8f2d2..00a49bd 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -456,6 +456,7 @@
     class SettingsObserver extends ContentObserver {
         int mUserId;
         boolean mRegistered = false;
+        @NonNull
         String mLastEnabled = "";
 
         /**
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 4536e04..65a22b9 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -809,7 +809,9 @@
                 if (user.isSystemOnly()) continue;
 
                 final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.id);
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.id);
                 if (provider != null) {
                     final IActivityManager am = ActivityManagerNative.getDefault();
                     try {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 329f716..07c10b0 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -49,6 +49,7 @@
 import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.INetd;
 import android.net.INetworkManagementEventObserver;
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
@@ -122,7 +123,7 @@
     private static final String TAG = "NetworkManagement";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     private static final String NETD_TAG = "NetdConnector";
-    private static final String NETD_SOCKET_NAME = "netd";
+    private static final String NETD_SERVICE_NAME = "netd";
 
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
@@ -188,6 +189,8 @@
     private final Handler mFgHandler;
     private final Handler mDaemonHandler;
 
+    private INetd mNetdService;
+
     private IBatteryStats mBatteryStats;
 
     private final Thread mThread;
@@ -306,7 +309,7 @@
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        return create(context, NETD_SOCKET_NAME);
+        return create(context, NETD_SERVICE_NAME);
     }
 
     public void systemReady() {
@@ -515,6 +518,15 @@
      * existing in-memory rules.
      */
     private void prepareNativeDaemon() {
+        boolean nativeServiceAvailable = false;
+        try {
+            mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME));
+            nativeServiceAvailable = mNetdService.isAlive();
+        } catch (RemoteException e) {}
+        if (!nativeServiceAvailable) {
+            Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME);
+        }
+
         mBandwidthControlEnabled = false;
 
         // only enable bandwidth control when support exists
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 306e933..3eb20a0 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -28,6 +28,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
@@ -464,9 +465,10 @@
             return null;
         }
         synchronized (mSpellCheckerMap) {
-            final String subtypeHashCodeStr = mSettings.getSelectedSpellCheckerSubtype();
+            final int subtypeHashCode =
+                    mSettings.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE);
             if (DBG) {
-                Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr);
+                Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCode);
             }
             final SpellCheckerInfo sci = getCurrentSpellChecker(null);
             if (sci == null || sci.getSubtypeCount() == 0) {
@@ -475,17 +477,12 @@
                 }
                 return null;
             }
-            final int hashCode;
-            if (!TextUtils.isEmpty(subtypeHashCodeStr)) {
-                hashCode = Integer.valueOf(subtypeHashCodeStr);
-            } else {
-                hashCode = 0;
-            }
-            if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
+            if (subtypeHashCode == SpellCheckerSubtype.SUBTYPE_ID_NONE
+                    && !allowImplicitlySelectedSubtype) {
                 return null;
             }
             String candidateLocale = null;
-            if (hashCode == 0) {
+            if (subtypeHashCode == 0) {
                 // Spell checker language settings == "auto"
                 final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
                 if (imm != null) {
@@ -507,7 +504,7 @@
             SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
-                if (hashCode == 0) {
+                if (subtypeHashCode == 0) {
                     final String scsLocale = scs.getLocale();
                     if (candidateLocale.equals(scsLocale)) {
                         return scs;
@@ -518,7 +515,7 @@
                             candidate = scs;
                         }
                     }
-                } else if (scs.hashCode() == hashCode) {
+                } else if (scs.hashCode() == subtypeHashCode) {
                     if (DBG) {
                         Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale
                                 + ", " + scs.getLocale());
@@ -1096,12 +1093,15 @@
             }
         }
 
-        private String getString(final String key) {
+        @Nullable
+        private String getString(@NonNull final String key, @Nullable final String defaultValue) {
+            final String result;
             if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
-                final String result = mCopyOnWriteDataStore.get(key);
-                return result != null ? result : "";
+                result = mCopyOnWriteDataStore.get(key);
+            } else {
+                result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
             }
-            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+            return result != null ? result : defaultValue;
         }
 
         private void putInt(final String key, final int value) {
@@ -1149,24 +1149,31 @@
             return mCurrentUserId;
         }
 
-        public void putSelectedSpellChecker(String sciId) {
-            putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+        public void putSelectedSpellChecker(@Nullable String sciId) {
+            if (TextUtils.isEmpty(sciId)) {
+                // OK to coalesce to null, since getSelectedSpellChecker() can take care of the
+                // empty data scenario.
+                putString(Settings.Secure.SELECTED_SPELL_CHECKER, null);
+            } else {
+                putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+            }
         }
 
         public void putSelectedSpellCheckerSubtype(int hashCode) {
-            putString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
+            putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode);
         }
 
         public void setSpellCheckerEnabled(boolean enabled) {
             putBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, enabled);
         }
 
+        @NonNull
         public String getSelectedSpellChecker() {
-            return getString(Settings.Secure.SELECTED_SPELL_CHECKER);
+            return getString(Settings.Secure.SELECTED_SPELL_CHECKER, "");
         }
 
-        public String getSelectedSpellCheckerSubtype() {
-            return getString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE);
+        public int getSelectedSpellCheckerSubtype(final int defaultValue) {
+            return getInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, defaultValue);
         }
 
         public boolean isSpellCheckerEnabled() {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d4dd505..1632f92 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -597,7 +597,7 @@
         if (sharedAccounts == null || sharedAccounts.length == 0) return;
         Account[] accounts = getAccountsAsUser(null, userId, mContext.getOpPackageName());
         int parentUserId = UserManager.isSplitSystemUser()
-                ? mUserManager.getUserInfo(userId).restrictedProfileParentId
+                ? getUserManager().getUserInfo(userId).restrictedProfileParentId
                 : UserHandle.USER_SYSTEM;
         if (parentUserId < 0) {
             Log.w(TAG, "User " + userId + " has shared accounts, but no parent user");
@@ -797,6 +797,7 @@
 
     @Override
     public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
+        Bundle.setDefusable(extras, true);
         final int callingUid = Binder.getCallingUid();
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "addAccountExplicitly: " + account
@@ -873,6 +874,7 @@
 
                 @Override
                 public void onResult(Bundle result) {
+                    Bundle.setDefusable(result, true);
                     if (result != null
                             && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
                         // Create a Session for the target user and pass in the bundle
@@ -946,6 +948,7 @@
     private void completeCloningAccount(IAccountManagerResponse response,
             final Bundle accountCredentials, final Account account, final UserAccounts targetUser,
             final int parentUserId){
+        Bundle.setDefusable(accountCredentials, true);
         long id = clearCallingIdentity();
         try {
             new Session(targetUser, response, account.type, false,
@@ -975,6 +978,7 @@
 
                 @Override
                 public void onResult(Bundle result) {
+                    Bundle.setDefusable(result, true);
                     // TODO: Anything to do if if succedded?
                     // TODO: If it failed: Show error notification? Should we remove the shadow
                     // account to avoid retries?
@@ -996,6 +1000,7 @@
 
     private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
             Bundle extras, boolean restricted, int callingUid) {
+        Bundle.setDefusable(extras, true);
         if (account == null) {
             return false;
         }
@@ -1061,7 +1066,7 @@
         for (UserInfo user : users) {
             if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) {
                 addSharedAccountAsUser(account, user.id);
-                if (mUserManager.isUserUnlocked(user.id)) {
+                if (getUserManager().isUserUnlocked(user.id)) {
                     mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
                             MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
                 }
@@ -1128,6 +1133,7 @@
 
         @Override
         public void onResult(Bundle result) {
+            Bundle.setDefusable(result, true);
             IAccountManagerResponse response = getResponseAndClose();
             if (response != null) {
                 try {
@@ -1270,7 +1276,7 @@
                          * Owner or system user account was renamed, rename the account for
                          * those users with which the account was shared.
                          */
-                        List<UserInfo> users = mUserManager.getUsers(true);
+                        List<UserInfo> users = getUserManager().getUsers(true);
                         for (UserInfo user : users) {
                             if (user.isRestricted()
                                     && (user.restrictedProfileParentId == parentUserId)) {
@@ -1286,7 +1292,7 @@
     }
 
     private boolean canHaveProfile(final int parentUserId) {
-        final UserInfo userInfo = mUserManager.getUserInfo(parentUserId);
+        final UserInfo userInfo = getUserManager().getUserInfo(parentUserId);
         return userInfo != null && userInfo.canHaveProfile();
     }
 
@@ -1429,6 +1435,7 @@
 
         @Override
         public void onResult(Bundle result) {
+            Bundle.setDefusable(result, true);
             if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
                     && !result.containsKey(AccountManager.KEY_INTENT)) {
                 final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
@@ -1477,7 +1484,7 @@
             int parentUserId = accounts.userId;
             if (canHaveProfile(parentUserId)) {
                 // Remove from any restricted profiles that are sharing this account.
-                List<UserInfo> users = mUserManager.getUsers(true);
+                List<UserInfo> users = getUserManager().getUsers(true);
                 for (UserInfo user : users) {
                     if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) {
                         removeSharedAccountAsUser(account, user.id, callingUid);
@@ -1880,6 +1887,7 @@
 
                 @Override
                 public void onResult(Bundle result) {
+                    Bundle.setDefusable(result, true);
                     if (result != null) {
                         String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
                         Bundle bundle = new Bundle();
@@ -1904,6 +1912,7 @@
             final boolean notifyOnAuthFailure,
             final boolean expectActivityLaunch,
             final Bundle loginOptions) {
+        Bundle.setDefusable(loginOptions, true);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "getAuthToken: " + account
                     + ", response " + response
@@ -2044,6 +2053,7 @@
 
                 @Override
                 public void onResult(Bundle result) {
+                    Bundle.setDefusable(result, true);
                     if (result != null) {
                         if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
                             Intent intent = newGrantCredentialsPermissionIntent(
@@ -2206,6 +2216,7 @@
     public void addAccount(final IAccountManagerResponse response, final String accountType,
             final String authTokenType, final String[] requiredFeatures,
             final boolean expectActivityLaunch, final Bundle optionsIn) {
+        Bundle.setDefusable(optionsIn, true);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "addAccount: accountType " + accountType
                     + ", response " + response
@@ -2280,6 +2291,7 @@
     public void addAccountAsUser(final IAccountManagerResponse response, final String accountType,
             final String authTokenType, final String[] requiredFeatures,
             final boolean expectActivityLaunch, final Bundle optionsIn, int userId) {
+        Bundle.setDefusable(optionsIn, true);
         int callingUid = Binder.getCallingUid();
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "addAccount: accountType " + accountType
@@ -2366,6 +2378,7 @@
             final String[] requiredFeatures,
             final boolean expectActivityLaunch,
             final Bundle optionsIn) {
+        Bundle.setDefusable(optionsIn, true);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG,
                     "startAddAccountSession: accountType " + accountType
@@ -2459,6 +2472,7 @@
 
         @Override
         public void onResult(Bundle result) {
+            Bundle.setDefusable(result, true);
             mNumResults++;
             Intent intent = null;
             if (result != null
@@ -2543,6 +2557,7 @@
             boolean expectActivityLaunch,
             Bundle appInfo,
             int userId) {
+        Bundle.setDefusable(sessionBundle, true);
         int callingUid = Binder.getCallingUid();
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG,
@@ -2698,6 +2713,7 @@
             final Bundle options,
             final boolean expectActivityLaunch,
             int userId) {
+        Bundle.setDefusable(options, true);
         int callingUid = Binder.getCallingUid();
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "confirmCredentials: " + account
@@ -2741,6 +2757,7 @@
     public void updateCredentials(IAccountManagerResponse response, final Account account,
             final String authTokenType, final boolean expectActivityLaunch,
             final Bundle loginOptions) {
+        Bundle.setDefusable(loginOptions, true);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "updateCredentials: " + account
                     + ", response " + response
@@ -2784,6 +2801,7 @@
             final String authTokenType,
             final boolean expectActivityLaunch,
             final Bundle loginOptions) {
+        Bundle.setDefusable(loginOptions, true);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG,
                     "startUpdateCredentialsSession: " + account + ", response " + response
@@ -2891,6 +2909,7 @@
 
                 @Override
                 public void onResult(Bundle result) {
+                    Bundle.setDefusable(result, true);
                     IAccountManagerResponse response = getResponseAndClose();
                     if (response == null) {
                         return;
@@ -3051,6 +3070,7 @@
 
         @Override
         public void onResult(Bundle result) {
+            Bundle.setDefusable(result, true);
             mNumResults++;
             if (result == null) {
                 onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
@@ -3685,6 +3705,7 @@
 
         @Override
         public void onResult(Bundle result) {
+            Bundle.setDefusable(result, true);
             mNumResults++;
             Intent intent = null;
             if (result != null) {
@@ -3825,7 +3846,7 @@
 
             final ActivityManager am = mContext.getSystemService(ActivityManager.class);
             if (am.isUserRunningAndLocked(mAccounts.userId)
-                    && !authenticatorInfo.componentInfo.encryptionAware) {
+                    && !authenticatorInfo.componentInfo.directBootAware) {
                 Slog.w(TAG, "Blocking binding to authenticator " + authenticatorInfo.componentName
                         + " which isn't encryption aware");
                 return false;
@@ -4730,7 +4751,7 @@
                 || callingUid == Process.myUid()) {
             return unfiltered;
         }
-        UserInfo user = mUserManager.getUserInfo(userAccounts.userId);
+        UserInfo user = getUserManager().getUserInfo(userAccounts.userId);
         if (user != null && user.isRestricted()) {
             String[] packages = mPackageManager.getPackagesForUid(callingUid);
             // If any of the packages is a white listed package, return the full set,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 95dbd0f..4f0f770 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -267,7 +267,7 @@
 import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.GET_PROVIDERS;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -1910,7 +1910,7 @@
                     mRecentTasks.loadUserRecentsLocked(userId);
                 }
                 if (userId == UserHandle.USER_SYSTEM) {
-                    startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+                    startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 }
                 installEncryptionUnawareProviders(userId);
                 break;
@@ -6913,6 +6913,14 @@
             }
         }
 
+        // We're going to be splicing together extras before sending, so we're
+        // okay poking into any contained extras.
+        if (intents != null) {
+            for (int i = 0; i < intents.length; i++) {
+                intents[i].setDefusable(true);
+            }
+        }
+
         final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
         final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
         final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
@@ -10953,7 +10961,7 @@
         // We're only interested in providers that are encryption unaware, and
         // we don't care about uninstalled apps, since there's no way they're
         // running at this point.
-        final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE;
+        final int matchFlags = GET_PROVIDERS | MATCH_DIRECT_BOOT_UNAWARE;
 
         synchronized (this) {
             final int NP = mProcessNames.getMap().size();
@@ -12874,7 +12882,7 @@
         synchronized (this) {
             // Only start up encryption-aware persistent apps; once user is
             // unlocked we'll come back around and start unaware apps
-            startPersistentApps(PackageManager.MATCH_ENCRYPTION_AWARE);
+            startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
 
             // Start up initial activity.
             mBooting = true;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index fa62c98..efa7420 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -620,7 +620,8 @@
                         && userManager.isUserUnlocked(parent.getUserHandle())
                         && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
                     rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
-                            PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ProcessStartLogger.java b/services/core/java/com/android/server/am/ProcessStartLogger.java
index d2aa966..39fbeb5 100644
--- a/services/core/java/com/android/server/am/ProcessStartLogger.java
+++ b/services/core/java/com/android/server/am/ProcessStartLogger.java
@@ -4,7 +4,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.app.AppGlobals;
-import android.auditing.SecurityLog;
+import android.app.admin.SecurityLog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index 7209814..fb1cda7 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -37,10 +37,7 @@
 import android.graphics.Bitmap;
 import android.os.Environment;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.UserHandle;
-import android.provider.Settings.System;
-import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -116,6 +113,7 @@
         // on file when we loaded them.
         if (mPersistedTaskIds.get(userId) == null) {
             mPersistedTaskIds.put(userId, mTaskPersister.loadPersistedTaskIdsForUser(userId));
+            Slog.i(TAG, "Loaded persisted task ids for user " + userId);
         }
     }
 
@@ -146,6 +144,12 @@
             TaskRecord task = get(i);
             if (task.isPersistable && (task.stack == null || !task.stack.isHomeStack())) {
                 // Set of persisted taskIds for task.userId should not be null here
+                // TODO Investigate why it can happen. For now initialize with an empty set
+                if (mPersistedTaskIds.get(task.userId) == null) {
+                    Slog.wtf(TAG, "No task ids found for userId " + task.userId + ". task=" + task
+                            + " mPersistedTaskIds=" + mPersistedTaskIds);
+                    mPersistedTaskIds.put(task.userId, new SparseBooleanArray());
+                }
                 mPersistedTaskIds.get(task.userId).put(task.taskId, true);
             }
         }
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 11fd3bc..ceb7db6 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -88,6 +88,7 @@
     private final ActivityStackSupervisor mStackSupervisor;
     private final RecentTasks mRecentTasks;
     private final SparseArray<SparseBooleanArray> mTaskIdsInFile = new SparseArray<>();
+    private final File mTaskIdsDir;
 
     /**
      * Value determines write delay mode as follows: < 0 We are Flushing. No delays between writes
@@ -139,12 +140,22 @@
             }
         }
 
+        mTaskIdsDir = new File(Environment.getDataDirectory(), "system_de");
         mStackSupervisor = stackSupervisor;
         mService = service;
         mRecentTasks = recentTasks;
         mLazyTaskWriterThread = new LazyTaskWriterThread("LazyTaskWriterThread");
     }
 
+    @VisibleForTesting
+    TaskPersister(File workingDir) {
+        mTaskIdsDir = workingDir;
+        mStackSupervisor = null;
+        mService = null;
+        mRecentTasks = null;
+        mLazyTaskWriterThread = new LazyTaskWriterThread("LazyTaskWriterThreadTest");
+    }
+
     void startPersisting() {
         if (!mLazyTaskWriterThread.isAlive()) {
             mLazyTaskWriterThread.start();
@@ -207,8 +218,8 @@
         return persistedTaskIds.clone();
     }
 
-    private void maybeWritePersistedTaskIdsForUser(@NonNull SparseBooleanArray taskIds,
-            int userId) {
+    @VisibleForTesting
+    void maybeWritePersistedTaskIdsForUser(@NonNull SparseBooleanArray taskIds, int userId) {
         if (userId < 0) {
             return;
         }
@@ -565,8 +576,12 @@
         return BitmapFactory.decodeFile(filename);
     }
 
-    static File getUserPersistedTaskIdsFile(int userId) {
-        return new File(Environment.getDataSystemDeDirectory(userId), PERSISTED_TASK_IDS_FILENAME);
+    private File getUserPersistedTaskIdsFile(int userId) {
+        File userTaskIdsDir = new File(mTaskIdsDir, String.valueOf(userId));
+        if (!userTaskIdsDir.exists() && !userTaskIdsDir.mkdirs()) {
+            Slog.e(TAG, "Error while creating user directory: " + userTaskIdsDir);
+        }
+        return new File(userTaskIdsDir, PERSISTED_TASK_IDS_FILENAME);
     }
 
     static File getUserTasksDir(int userId) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e7580f4..f471af6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -205,7 +205,6 @@
     private static final int MSG_SET_FORCE_USE = 8;
     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
     private static final int MSG_SET_ALL_VOLUMES = 10;
-    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
     private static final int MSG_REPORT_NEW_ROUTES = 12;
     private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
@@ -217,7 +216,6 @@
     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
     private static final int MSG_SYSTEM_READY = 21;
     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
-    private static final int MSG_PERSIST_MICROPHONE_MUTE = 23;
     private static final int MSG_UNMUTE_STREAM = 24;
     private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
     private static final int MSG_INDICATE_SYSTEM_READY = 26;
@@ -665,6 +663,7 @@
         // array initialized by updateStreamVolumeAlias()
         updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
         readPersistedSettings();
+        readUserRestrictions();
         mSettingsObserver = new SettingsObserver();
         createStreamStates();
 
@@ -1111,35 +1110,6 @@
                 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
                 UserHandle.USER_CURRENT);
 
-        final int currentUser = getCurrentUserId();
-
-        // In addition to checking the system setting, also check the current user restriction.
-        // Because of the delay before persisting VOLUME_MASTER_MUTE, there's a window where
-        // DISALLOW_ADJUST_VOLUME will be ignored when it's set right before switching users.
-        boolean masterMute = (System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
-                0, UserHandle.USER_CURRENT) == 1)
-                || mUserManagerInternal.getUserRestriction(
-                    currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
-        if (mUseFixedVolume) {
-            masterMute = false;
-            AudioSystem.setMasterVolume(1.0f);
-        }
-        if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
-        }
-        setSystemAudioMute(masterMute);
-        AudioSystem.setMasterMute(masterMute);
-        broadcastMasterMuteStatus(masterMute);
-
-        boolean microphoneMute =
-                (System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1)
-                || mUserManagerInternal.getUserRestriction(
-                        currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
-        if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
-        }
-        AudioSystem.muteMicrophone(microphoneMute);
-
         updateMasterMono(cr);
 
         // Each stream will read its own persisted settings
@@ -1156,6 +1126,31 @@
         mVolumeController.loadSettings(cr);
     }
 
+    private void readUserRestrictions() {
+        final int currentUser = getCurrentUserId();
+
+        // Check the current user restriction.
+        boolean masterMute = mUserManagerInternal.getUserRestriction(
+                    currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
+        if (mUseFixedVolume) {
+            masterMute = false;
+            AudioSystem.setMasterVolume(1.0f);
+        }
+        if (DEBUG_VOL) {
+            Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
+        }
+        setSystemAudioMute(masterMute);
+        AudioSystem.setMasterMute(masterMute);
+        broadcastMasterMuteStatus(masterMute);
+
+        boolean microphoneMute = mUserManagerInternal.getUserRestriction(
+                currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+        if (DEBUG_VOL) {
+            Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
+        }
+        AudioSystem.muteMicrophone(microphoneMute);
+    }
+
     private int rescaleIndex(int index, int srcStream, int dstStream) {
         return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
     }
@@ -1295,7 +1290,7 @@
             // Check if the ringer mode handles this adjustment. If it does we don't
             // need to adjust the volume further.
             final int result = checkForRingerModeChange(aliasIndex, direction, step,
-                    streamState.mIsMuted, caller);
+                    streamState.mIsMuted);
             adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
             // If suppressing a volume adjustment in silent mode, display the UI hint
             if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -1389,8 +1384,13 @@
                         synchronized (mHdmiPlaybackClient) {
                             int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
                                     KeyEvent.KEYCODE_VOLUME_UP;
-                            mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
-                            mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
+                            final long ident = Binder.clearCallingIdentity();
+                            try {
+                                mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
+                                mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
+                            } finally {
+                                Binder.restoreCallingIdentity(ident);
+                            }
                         }
                     }
                 }
@@ -1911,20 +1911,12 @@
             if (mute != AudioSystem.getMasterMute()) {
                 setSystemAudioMute(mute);
                 AudioSystem.setMasterMute(mute);
-                // Post a persist master volume msg
-                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                        : 0, userId, null, PERSIST_DELAY);
                 sendMasterMuteUpdate(mute, flags);
 
                 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
                 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
                 sendBroadcastToAll(intent);
             }
-        } else {
-            // If not the current user just persist the setting which will be loaded
-            // on user switch.
-            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                    : 0, userId, null, PERSIST_DELAY);
         }
     }
 
@@ -2017,8 +2009,6 @@
             AudioSystem.muteMicrophone(on);
         }
         // Post a persist microphone msg.
-        sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
-                : 0, userId, null, PERSIST_DELAY);
     }
 
     @Override
@@ -2607,6 +2597,7 @@
     private void readAudioSettings(boolean userSwitch) {
         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
         readPersistedSettings();
+        readUserRestrictions();
 
         // restore volume settings
         int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3375,8 +3366,7 @@
      * adjusting volume. If so, this will set the proper ringer mode and volume
      * indices on the stream states.
      */
-    private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
-            String caller) {
+    private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
         final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
         int result = FLAG_ADJUST_VOLUME;
         int ringerMode = getRingerModeInternal();
@@ -3465,11 +3455,6 @@
             break;
         }
 
-        if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
-                && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
-            throw new SecurityException("Not allowed to change Do Not Disturb state");
-        }
-
         setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
 
         mPrevVolDirection = direction;
@@ -4545,16 +4530,6 @@
                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
                     break;
 
-                case MSG_PERSIST_MASTER_VOLUME_MUTE:
-                    if (mUseFixedVolume) {
-                        return;
-                    }
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.VOLUME_MASTER_MUTE,
-                                                 msg.arg1,
-                                                 msg.arg2);
-                    break;
-
                 case MSG_PERSIST_RINGER_MODE:
                     // note that the value persisted is the current ringer mode, not the
                     // value of ringer mode as of the time the request was made to persist
@@ -4677,15 +4652,11 @@
                             Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
                             UserHandle.USER_CURRENT);
                     break;
-                case MSG_PERSIST_MICROPHONE_MUTE:
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.MICROPHONE_MUTE,
-                                                 msg.arg1,
-                                                 msg.arg2);
-                    break;
+
                 case MSG_UNMUTE_STREAM:
                     onUnmuteStream(msg.arg1, msg.arg2);
                     break;
+
                 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
                     onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
                     break;
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
index 8195319..d62a0b3 100644
--- a/services/core/java/com/android/server/connectivity/ApfFilter.java
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -90,7 +90,7 @@
     }
 
     private static final String TAG = "ApfFilter";
-    private static final boolean VDBG = true;
+    private static final boolean VDBG = false;
 
     private final ConnectivityService mConnectivityService;
     private final NetworkAgentInfo mNai;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 03191a0..28170f2 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -286,6 +286,7 @@
                 UserHandle.getCallingUserId());
     }
 
+    @Override
     public void unregisterContentObserver(IContentObserver observer) {
         if (observer == null) {
             throw new IllegalArgumentException("You must pass a valid observer");
@@ -409,7 +410,9 @@
         }
     }
 
+    @Override
     public void requestSync(Account account, String authority, Bundle extras) {
+        Bundle.setDefusable(extras, true);
         ContentResolver.validateSyncExtrasBundle(extras);
         int userId = UserHandle.getCallingUserId();
         int uId = Binder.getCallingUid();
@@ -438,6 +441,7 @@
      * Depending on the request, we enqueue to suit in the SyncManager.
      * @param request The request object. Validation of this object is done by its builder.
      */
+    @Override
     public void sync(SyncRequest request) {
         syncAsUser(request, UserHandle.getCallingUserId());
     }
@@ -446,6 +450,7 @@
      * If the user id supplied is different to the calling user, the caller must hold the
      * INTERACT_ACROSS_USERS_FULL permission.
      */
+    @Override
     public void syncAsUser(SyncRequest request, int userId) {
         enforceCrossUserPermission(userId, "no permission to request sync as user: " + userId);
         int callerUid = Binder.getCallingUid();
@@ -544,6 +549,7 @@
         }
     }
 
+    @Override
     public void cancelRequest(SyncRequest request) {
         SyncManager syncManager = getSyncManager();
         if (syncManager == null) return;
@@ -678,6 +684,7 @@
     @Override
     public void addPeriodicSync(Account account, String authority, Bundle extras,
                                 long pollFrequency) {
+        Bundle.setDefusable(extras, true);
         if (account == null) {
             throw new IllegalArgumentException("Account must not be null");
         }
@@ -706,7 +713,9 @@
         }
     }
 
+    @Override
     public void removePeriodicSync(Account account, String authority, Bundle extras) {
+        Bundle.setDefusable(extras, true);
         if (account == null) {
             throw new IllegalArgumentException("Account must not be null");
         }
@@ -728,7 +737,7 @@
         }
     }
 
-
+    @Override
     public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName,
                                                ComponentName cname) {
         if (account == null) {
@@ -750,6 +759,7 @@
         }
     }
 
+    @Override
     public int getIsSyncable(Account account, String providerName) {
         return getIsSyncableAsUser(account, providerName, UserHandle.getCallingUserId());
     }
@@ -758,6 +768,7 @@
      * If the user id supplied is different to the calling user, the caller must hold the
      * INTERACT_ACROSS_USERS_FULL permission.
      */
+    @Override
     public int getIsSyncableAsUser(Account account, String providerName, int userId) {
         enforceCrossUserPermission(userId,
                 "no permission to read the sync settings for user " + userId);
@@ -777,6 +788,7 @@
         return -1;
     }
 
+    @Override
     public void setIsSyncable(Account account, String providerName, int syncable) {
         if (TextUtils.isEmpty(providerName)) {
             throw new IllegalArgumentException("Authority must not be empty");
@@ -848,11 +860,11 @@
         }
     }
 
+    @Override
     public boolean isSyncActive(Account account, String authority, ComponentName cname) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
         int userId = UserHandle.getCallingUserId();
-        int callingUid = Binder.getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
@@ -866,6 +878,7 @@
         }
     }
 
+    @Override
     public List<SyncInfo> getCurrentSyncs() {
         return getCurrentSyncsAsUser(UserHandle.getCallingUserId());
     }
@@ -874,6 +887,7 @@
      * If the user id supplied is different to the calling user, the caller must hold the
      * INTERACT_ACROSS_USERS_FULL permission.
      */
+    @Override
     public List<SyncInfo> getCurrentSyncsAsUser(int userId) {
         enforceCrossUserPermission(userId,
                 "no permission to read the sync settings for user " + userId);
@@ -892,6 +906,7 @@
         }
     }
 
+    @Override
     public SyncStatusInfo getSyncStatus(Account account, String authority, ComponentName cname) {
         return getSyncStatusAsUser(account, authority, cname, UserHandle.getCallingUserId());
     }
@@ -900,6 +915,7 @@
      * If the user id supplied is different to the calling user, the caller must hold the
      * INTERACT_ACROSS_USERS_FULL permission.
      */
+    @Override
     public SyncStatusInfo getSyncStatusAsUser(Account account, String authority,
                                               ComponentName cname, int userId) {
         if (TextUtils.isEmpty(authority)) {
@@ -911,7 +927,6 @@
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
 
-        int callerUid = Binder.getCallingUid();
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
@@ -930,6 +945,7 @@
         }
     }
 
+    @Override
     public boolean isSyncPending(Account account, String authority, ComponentName cname) {
         return isSyncPendingAsUser(account, authority, cname, UserHandle.getCallingUserId());
     }
@@ -941,7 +957,6 @@
                 "no permission to read the sync stats");
         enforceCrossUserPermission(userId,
                 "no permission to retrieve the sync settings for user " + userId);
-        int callerUid = Binder.getCallingUid();
         long identityToken = clearCallingIdentity();
         SyncManager syncManager = getSyncManager();
         if (syncManager == null) return false;
@@ -959,6 +974,7 @@
         }
     }
 
+    @Override
     public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
         long identityToken = clearCallingIdentity();
         try {
@@ -971,6 +987,7 @@
         }
     }
 
+    @Override
     public void removeStatusChangeListener(ISyncStatusObserver callback) {
         long identityToken = clearCallingIdentity();
         try {
@@ -1027,6 +1044,7 @@
 
     @Override
     public void putCache(String packageName, Uri key, Bundle value, int userId) {
+        Bundle.setDefusable(value, true);
         enforceCrossUserPermission(userId, TAG);
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
         mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
@@ -1113,6 +1131,7 @@
                 }
             }
 
+            @Override
             public void binderDied() {
                 synchronized (observersLock) {
                     removeObserverLocked(observer);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 033a243..3c04b78 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1109,7 +1109,8 @@
         final PackageManager pm = mContext.getPackageManager();
         Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
         for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
-                PackageManager.GET_META_DATA | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE)) {
+                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE)) {
             final ActivityInfo activityInfo = resolveInfo.activityInfo;
             final int priority = resolveInfo.priority;
             visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
@@ -1125,7 +1126,8 @@
                 ActivityInfo receiver = pm.getReceiverInfo(
                         new ComponentName(d.packageName, d.receiverName),
                         PackageManager.GET_META_DATA
-                                | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                                | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
             } catch (NameNotFoundException ex) {
             }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index cee46195..9fd7f90 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -311,10 +311,10 @@
             }
 
             toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
-        }
-        startTrackingJob(jobStatus, toCancel);
-        if (toCancel != null) {
-            cancelJobImpl(toCancel);
+            if (toCancel != null) {
+                cancelJobImpl(toCancel);
+            }
+            startTrackingJob(jobStatus, toCancel);
         }
         mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
         return JobScheduler.RESULT_SUCCESS;
@@ -1219,7 +1219,8 @@
             final ComponentName service = job.getService();
             try {
                 ServiceInfo si = pm.getServiceInfo(service,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                         UserHandle.getUserId(uid));
                 if (si == null) {
                     throw new IllegalArgumentException("No such service " + service);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 3acd2ca..0b4f7f0 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -688,7 +688,7 @@
                 // global background data policy
                 if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
                 synchronized (mRulesLock) {
-                    updateRulesForUidLocked(uid);
+                    updateRestrictDataRulesForUidLocked(uid);
                 }
             }
         }
@@ -706,7 +706,7 @@
             if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
             synchronized (mRulesLock) {
                 mUidPolicy.delete(uid);
-                updateRulesForUidLocked(uid);
+                updateRestrictDataRulesForUidLocked(uid);
                 writePolicyLocked();
             }
         }
@@ -1676,7 +1676,7 @@
         mUidPolicy.put(uid, policy);
 
         // uid policy changed, recompute rules and persist policy.
-        updateRulesForUidLocked(uid);
+        updateRestrictDataRulesForUidLocked(uid);
         if (persist) {
             writePolicyLocked();
         }
@@ -1731,8 +1731,6 @@
             }
             writePolicy = true;
         }
-        updateRulesForGlobalChangeLocked(true);
-
         // Remove associated UID policies
         int[] uids = new int[0];
         for (int i = 0; i < mUidPolicy.size(); i++) {
@@ -1745,11 +1743,12 @@
         if (uids.length > 0) {
             for (int uid : uids) {
                 mUidPolicy.delete(uid);
-                updateRulesForUidLocked(uid);
             }
             writePolicy = true;
         }
 
+        updateRulesForGlobalChangeLocked(true);
+
         if (writePolicy) {
             writePolicyLocked();
         }
@@ -1896,7 +1895,7 @@
             maybeRefreshTrustedTime();
             synchronized (mRulesLock) {
                 mRestrictBackground = restrictBackground;
-                updateRulesForGlobalChangeLocked(true);
+                updateRulesForRestrictDataLocked();
                 updateNotificationsLocked();
                 writePolicyLocked();
             }
@@ -2303,7 +2302,7 @@
 
     /**
      * Process state of UID changed; if needed, will trigger
-     * {@link #updateRulesForUidLocked(int)}.
+     * {@link #updateRestrictDataRulesForUidLocked(int)}.
      */
     void updateUidStateLocked(int uid, int uidState) {
         final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
@@ -2345,7 +2344,7 @@
         final boolean oldForeground = oldUidState <= ActivityManager.PROCESS_STATE_TOP;
         final boolean newForeground = newUidState <= ActivityManager.PROCESS_STATE_TOP;
         if (oldForeground != newForeground) {
-            updateRulesForUidLocked(uid);
+            updateRestrictDataRulesForUidLocked(uid);
         }
     }
 
@@ -2369,7 +2368,7 @@
         for (int i = 0; i < size; i++) {
             if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_TOP) {
                 final int uid = mUidState.keyAt(i);
-                updateRulesForUidLocked(uid);
+                updateRestrictDataRulesForUidLocked(uid);
             }
         }
     }
@@ -2444,8 +2443,6 @@
                 setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
             }
         }
-
-        updateRulesForUidLocked(uid);
     }
 
     void updateRulesForAppIdleLocked() {
@@ -2482,35 +2479,47 @@
         } else {
             setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
         }
-
-        updateRulesForUidLocked(uid);
     }
 
     void updateRulesForAppIdleParoleLocked() {
         boolean enableChain = !mUsageStats.isAppIdleParoleOn();
         enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
-        updateRulesForUidsLocked(mUidFirewallStandbyRules);
     }
 
     /**
      * Update rules that might be changed by {@link #mRestrictBackground},
      * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
      */
-    void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
+    private void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
         long start;
         if (LOGD) start = System.currentTimeMillis();
 
-        final PackageManager pm = mContext.getPackageManager();
-
         updateRulesForDeviceIdleLocked();
         updateRulesForAppIdleLocked();
         updateRulesForRestrictPowerLocked();
+        updateRulesForRestrictDataLocked();
+
+        // If the set of restricted networks may have changed, re-evaluate those.
+        if (restrictedNetworksChanged) {
+            normalizePoliciesLocked();
+            updateNetworkRulesLocked();
+        }
+        if (LOGD) {
+            final long delta = System.currentTimeMillis() - start;
+            Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
+                    + delta + "ms");
+        }
+    }
+
+    private void updateRulesForRestrictDataLocked() {
+        final PackageManager pm = mContext.getPackageManager();
 
         // update rules for all installed applications
         final List<UserInfo> users = mUserManager.getUsers();
         final List<ApplicationInfo> apps = pm.getInstalledApplications(
-                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS
-                        | PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_DISABLED_COMPONENTS
+                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
 
         final int usersSize = users.size();
         final int appsSize = apps.size();
@@ -2519,27 +2528,16 @@
             for (int j = 0; j < appsSize; j++) {
                 final ApplicationInfo app = apps.get(j);
                 final int uid = UserHandle.getUid(user.id, app.uid);
-                updateRulesForUidLocked(uid);
+                updateRestrictDataRulesForUidLocked(uid);
             }
         }
 
         // limit data usage for some internal system services
-        updateRulesForUidLocked(android.os.Process.MEDIA_UID);
-        updateRulesForUidLocked(android.os.Process.DRM_UID);
-
-        // If the set of restricted networks may have changed, re-evaluate those.
-        if (restrictedNetworksChanged) {
-            normalizePoliciesLocked();
-            updateNetworkRulesLocked();
-        }
-        if (LOGD) {
-          final long delta = System.currentTimeMillis() - start;
-          Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
-                  + delta + "ms");
-        }
+        updateRestrictDataRulesForUidLocked(android.os.Process.MEDIA_UID);
+        updateRestrictDataRulesForUidLocked(android.os.Process.DRM_UID);
     }
 
-    void updateRulesForTempWhitelistChangeLocked() {
+    private void updateRulesForTempWhitelistChangeLocked() {
         final List<UserInfo> users = mUserManager.getUsers();
         for (int i = 0; i < users.size(); i++) {
             final UserInfo user = users.get(i);
@@ -2577,12 +2575,6 @@
         return true;
     }
 
-    void updateRulesForUidsLocked(SparseIntArray uids) {
-        for (int i = 0; i < uids.size(); i++) {
-            updateRulesForUidLocked(uids.keyAt(i));
-        }
-    }
-
     /**
      * Checks if an uid has INTERNET permissions.
      * <p>
@@ -2600,72 +2592,45 @@
     }
 
     /**
-     * Applies network rules to bandwidth and firewall controllers based on uid policy.
+     * Applies network rules to bandwidth controllers based on uid policy.
+     *
      * @param uid The uid for which to apply the latest policy
      */
-    void updateRulesForUidLocked(int uid) {
+    private void updateRestrictDataRulesForUidLocked(int uid) {
         if (!isUidValidForRules(uid) || !hasInternetPermissions(uid)) return;
 
         final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
         final boolean uidForeground = isUidForegroundLocked(uid);
 
         // Derive active rules based on policy and active state
-        int appId = UserHandle.getAppId(uid);
-        int uidRules = RULE_ALLOW_ALL;
-        if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
-            // uid in background, and policy says to block metered data
-            uidRules = RULE_REJECT_METERED;
-        } else if (mRestrictBackground) {
-            if (!uidForeground) {
-                // uid in background, global background disabled, and this uid is not on the white
-                // list of those allowed background access while global background is disabled
-                if (!mRestrictBackgroundWhitelistUids.get(uid)) {
-                    uidRules = RULE_REJECT_METERED;
-                }
-            }
-        } else if (mRestrictPower) {
-            final boolean whitelisted = mPowerSaveWhitelistExceptIdleAppIds.get(appId)
-                    || mPowerSaveTempWhitelistAppIds.get(appId);
-            if (!whitelisted && !uidForeground
-                    && (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) {
-                // uid is in background, restrict power use mode is on (so we want to
-                // restrict all background network access), and this uid is not on the
-                // white list of those allowed background access.
-                uidRules = RULE_REJECT_METERED;
+        int newRule = RULE_ALLOW_ALL;
+
+        if (!uidForeground) {
+            // If the app is not in foreground, reject access if:
+            // - app is blacklisted by policy or
+            // - data saver mode is and app is not whitelisted
+            if (((uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0)
+                || (mRestrictBackground && !mRestrictBackgroundWhitelistUids.get(uid))) {
+                newRule = RULE_REJECT_METERED;
             }
         }
 
-        // Check dozable state, which is whitelist
-        if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)
-                && mUidFirewallDozableRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) {
-            uidRules = RULE_REJECT_ALL;
-        }
+        final int oldRule = mUidRules.get(uid);
+        if (LOGV) Log.v(TAG, "updateBandwithControllerRulesForUidLocked(" + uid + "): oldRule = "
+                + oldRule + ", newRule = " + newRule);
 
-        // Check powersave state, which is whitelist
-        if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)
-                && mUidFirewallPowerSaveRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) {
-            uidRules = RULE_REJECT_ALL;
-        }
-
-        // Check standby state, which is blacklist
-        if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)
-                && mUidFirewallStandbyRules.get(uid, FIREWALL_RULE_DEFAULT) == FIREWALL_RULE_DENY) {
-            uidRules = RULE_REJECT_ALL;
-        }
-
-        final int oldRules = mUidRules.get(uid);
-        if (uidRules == RULE_ALLOW_ALL) {
+        if (newRule == RULE_ALLOW_ALL) {
             mUidRules.delete(uid);
         } else {
-            mUidRules.put(uid, uidRules);
+            mUidRules.put(uid, newRule);
         }
 
-        final boolean rejectMetered = (uidRules == RULE_REJECT_METERED);
+        final boolean rejectMetered = (newRule == RULE_REJECT_METERED);
         setUidNetworkRules(uid, rejectMetered);
 
         // dispatch changed rule to existing listeners
-        if (oldRules != uidRules) {
-            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
+        if (oldRule != newRule) {
+            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newRule).sendToTarget();
         }
 
         try {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3baf894..274a73f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -160,6 +160,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
@@ -276,9 +277,6 @@
     // Persistent storage for notification policy
     private AtomicFile mPolicyFile;
 
-    // Temporary holder for <blocked-packages> config coming from old policy files.
-    private HashSet<String> mBlockedPackages = new HashSet<String>();
-
     private static final int DB_VERSION = 1;
 
     private static final String TAG_NOTIFICATION_POLICY = "notification-policy";
@@ -354,27 +352,7 @@
         final XmlPullParser parser = Xml.newPullParser();
         parser.setInput(stream, StandardCharsets.UTF_8.name());
 
-        int type;
-        String tag;
-        int version = DB_VERSION;
-        while ((type = parser.next()) != END_DOCUMENT) {
-            tag = parser.getName();
-            if (type == START_TAG) {
-                if (TAG_NOTIFICATION_POLICY.equals(tag)) {
-                    version = Integer.parseInt(
-                            parser.getAttributeValue(null, ATTR_VERSION));
-                } else if (TAG_BLOCKED_PKGS.equals(tag)) {
-                    while ((type = parser.next()) != END_DOCUMENT) {
-                        tag = parser.getName();
-                        if (TAG_PACKAGE.equals(tag)) {
-                            mBlockedPackages.add(
-                                    parser.getAttributeValue(null, ATTR_NAME));
-                        } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
-                            break;
-                        }
-                    }
-                }
-            }
+        while (parser.next() != END_DOCUMENT) {
             mZenModeHelper.readXml(parser, forRestore);
             mRankingHelper.readXml(parser, forRestore);
         }
@@ -383,7 +361,6 @@
     private void loadPolicyFile() {
         if (DBG) Slog.d(TAG, "loadPolicyFile");
         synchronized(mPolicyFile) {
-            mBlockedPackages.clear();
 
             FileInputStream infile = null;
             try {
@@ -941,7 +918,7 @@
         final File systemDir = new File(Environment.getDataDirectory(), "system");
         mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
 
-        importOldBlockDb();
+        syncBlockDb();
 
         // This is a MangedServices object that keeps track of the listeners.
         mListeners = new NotificationListeners();
@@ -1041,22 +1018,43 @@
     }
 
     /**
-     * Read the old XML-based app block database and import those blockages into the AppOps system.
+     * Make sure the XML config and the the AppOps system agree about blocks.
      */
-    private void importOldBlockDb() {
+    private void syncBlockDb() {
         loadPolicyFile();
 
-        PackageManager pm = getContext().getPackageManager();
-        for (String pkg : mBlockedPackages) {
-            PackageInfo info = null;
-            try {
-                info = pm.getPackageInfo(pkg, 0);
-                setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false);
-            } catch (NameNotFoundException e) {
-                // forget you
+        // sync bans from ranker into app opps
+        Map<Integer, String> packageBans = mRankingHelper.getPackageBans();
+        for(Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int uid = ban.getKey();
+            final String packageName = ban.getValue();
+            setNotificationsEnabledForPackageImpl(packageName, uid, false);
+        }
+
+        // sync bans from app opps into ranker
+        packageBans.clear();
+        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
+            final int userId = user.getUserHandle().getIdentifier();
+            final PackageManager packageManager = getContext().getPackageManager();
+            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
+            final int packageCount = packages.size();
+            for (int p = 0; p < packageCount; p++) {
+                final String packageName = packages.get(p).packageName;
+                try {
+                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
+                    if (!checkNotificationOp(packageName, uid)) {
+                        packageBans.put(uid, packageName);
+                    }
+                } catch (NameNotFoundException e) {
+                    // forget you
+                }
             }
         }
-        mBlockedPackages.clear();
+        for (Entry<Integer, String> ban : packageBans.entrySet()) {
+            mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE);
+        }
+
+        savePolicyFile();
     }
 
     @Override
@@ -1261,6 +1259,8 @@
             checkCallerIsSystem();
 
             setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+            mRankingHelper.setEnabled(pkg, uid, enabled);
+            savePolicyFile();
         }
 
         /**
@@ -1852,6 +1852,16 @@
         }
 
         private boolean checkPolicyAccess(String pkg) {
+            if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
+                    android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
+                return true;
+            }
+            if (mAudioManagerInternal != null) {
+                final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
+                if (vcuid > 0 && Binder.getCallingUid() == vcuid) {
+                    return true;
+                }
+            }
             return checkPackagePolicyAccess(pkg) || mListeners.isComponentEnabledForPackage(pkg);
         }
 
@@ -1946,7 +1956,7 @@
         public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {;
             enforceSystemOrSystemUIOrSamePackage(pkg,
                     "request policy access status for another package");
-            return checkPackagePolicyAccess(pkg);
+            return checkPolicyAccess(pkg);
         }
 
         @Override
@@ -2034,21 +2044,8 @@
         JSONObject dump = new JSONObject();
         try {
             dump.put("service", "Notification Manager");
-            JSONArray bans = new JSONArray();
-            try {
-                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
-                for (Integer userId : packageBans.keySet()) {
-                    for (String packageName : packageBans.get(userId)) {
-                        JSONObject ban = new JSONObject();
-                        ban.put("userId", userId);
-                        ban.put("packageName", packageName);
-                        bans.put(ban);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // pass
-            }
-            dump.put("bans", bans);
+            dump.put("bans", mRankingHelper.dumpBansJson(filter));
+            dump.put("ranking", mRankingHelper.dumpJson(filter));
             dump.put("stats", mUsageStats.dumpJson(filter));
         } catch (JSONException e) {
             e.printStackTrace();
@@ -2175,47 +2172,9 @@
                     r.dump(pw, "      ", getContext(), filter.redact);
                 }
             }
-
-            try {
-                pw.println("\n  Banned Packages:");
-                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
-                for (Integer userId : packageBans.keySet()) {
-                    for (String packageName : packageBans.get(userId)) {
-                        pw.println("    " + userId + ": " + packageName);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // pass
-            }
         }
     }
 
-    private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter)
-            throws NameNotFoundException {
-        ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>();
-        ArrayList<String> packageNames = new ArrayList<>();
-        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-            final PackageManager packageManager = getContext().getPackageManager();
-            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
-            final int packageCount = packages.size();
-            for (int p = 0; p < packageCount; p++) {
-                final String packageName = packages.get(p).packageName;
-                if (filter == null || filter.matches(packageName)) {
-                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
-                    if (!checkNotificationOp(packageName, uid)) {
-                        packageNames.add(packageName);
-                    }
-                }
-            }
-            if (!packageNames.isEmpty()) {
-                packageBans.put(userId, packageNames);
-                packageNames = new ArrayList<>();
-            }
-        }
-        return packageBans;
-    }
-
     /**
      * The private API only accessible to the system process.
      */
@@ -3598,6 +3557,9 @@
         public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
             if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
                     + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)));
+            if (mRankerServicePackageName == null) {
+                return;
+            }
 
             if (pkgList != null && (pkgList.length > 0)) {
                 for (String pkgName : pkgList) {
@@ -3610,6 +3572,10 @@
 
         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, null);
             Iterator<ComponentName> iterator = rankerComponents.iterator();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index fd96a78..4a41705 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -25,6 +25,11 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -33,6 +38,8 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class RankingHelper implements RankingConfig {
     private static final String TAG = "RankingHelper";
@@ -358,6 +365,14 @@
         updateConfig();
     }
 
+    public void setEnabled(String packageName, int uid, boolean enabled) {
+        boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE;
+        if (wasEnabled == enabled) {
+            return;
+        }
+        setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE);
+    }
+
     public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
         if (filter == null) {
             final int N = mSignalExtractors.length;
@@ -398,17 +413,97 @@
                 }
                 if (r.priority != DEFAULT_PRIORITY) {
                     pw.print(" priority=");
-                    pw.print(Ranking.importanceToString(r.priority));
+                    pw.print(Notification.priorityToString(r.priority));
                 }
                 if (r.visibility != DEFAULT_VISIBILITY) {
                     pw.print(" visibility=");
-                    pw.print(Ranking.importanceToString(r.visibility));
+                    pw.print(Notification.visibilityToString(r.visibility));
                 }
                 pw.println();
             }
         }
     }
 
+    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
+        JSONObject ranking = new JSONObject();
+        JSONArray records = new JSONArray();
+        try {
+            ranking.put("noUid", mRestoredWithoutUids.size());
+        } catch (JSONException e) {
+           // pass
+        }
+        final int N = mRecords.size();
+        for (int i = 0; i < N; i++) {
+            final Record r = mRecords.valueAt(i);
+            if (filter == null || filter.matches(r.pkg)) {
+                JSONObject record = new JSONObject();
+                try {
+                    record.put("userId", UserHandle.getUserId(r.uid));
+                    record.put("packageName", r.pkg);
+                    if (r.importance != DEFAULT_IMPORTANCE) {
+                        record.put("importance", Ranking.importanceToString(r.importance));
+                    }
+                    if (r.priority != DEFAULT_PRIORITY) {
+                        record.put("priority", Notification.priorityToString(r.priority));
+                    }
+                    if (r.visibility != DEFAULT_VISIBILITY) {
+                        record.put("visibility", Notification.visibilityToString(r.visibility));
+                    }
+                } catch (JSONException e) {
+                   // pass
+                }
+                records.put(record);
+            }
+        }
+        try {
+            ranking.put("records", records);
+        } catch (JSONException e) {
+            // pass
+        }
+        return ranking;
+    }
+
+    /**
+     * Dump only the ban information as structured JSON for the stats collector.
+     *
+     * This is intentionally redundant with {#link dumpJson} because the old
+     * scraper will expect this format.
+     *
+     * @param filter
+     * @return
+     */
+    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) {
+        JSONArray bans = new JSONArray();
+        Map<Integer, String> packageBans = getPackageBans();
+        for(Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int userId = UserHandle.getUserId(ban.getKey());
+            final String packageName = ban.getValue();
+            if (filter == null || filter.matches(packageName)) {
+                JSONObject banJson = new JSONObject();
+                try {
+                    banJson.put("userId", userId);
+                    banJson.put("packageName", packageName);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+                bans.put(banJson);
+            }
+        }
+        return bans;
+    }
+
+    public Map<Integer, String> getPackageBans() {
+        final int N = mRecords.size();
+        ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
+        for (int i = 0; i < N; i++) {
+            final Record r = mRecords.valueAt(i);
+            if (r.importance == Ranking.IMPORTANCE_NONE) {
+                packageBans.put(r.uid, r.pkg);
+            }
+        }
+        return packageBans;
+    }
+
     public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
         if (queryReplace || pkgList == null || pkgList.length == 0
                 || mRestoredWithoutUids.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 27c8293..13a96ae 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -59,7 +59,8 @@
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
-    private static final int DEFAULT_FLAGS = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+    private static final int DEFAULT_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE
+            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 
     private static final String AUDIO_MIME_TYPE = "audio/mpeg";
 
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 5b0ceca..2f0532a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -218,7 +218,8 @@
             int packageUid = -1;
             try {
                 packageUid = mPm.getPackageUidAsUser(callingPackage,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
                         UserHandle.getUserId(getCallingUid()));
             } catch (NameNotFoundException e) {
@@ -256,7 +257,9 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return new ParceledListSlice<>(apps);
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -274,7 +277,9 @@
             long ident = Binder.clearCallingIdentity();
             try {
                 ResolveInfo app = mPm.resolveActivityAsUser(intent,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return app;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -293,7 +298,9 @@
             try {
                 IPackageManager pm = AppGlobals.getPackageManager();
                 PackageInfo info = pm.getPackageInfo(packageName,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return info != null && info.applicationInfo.enabled;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -421,7 +428,9 @@
             try {
                 IPackageManager pm = AppGlobals.getPackageManager();
                 ActivityInfo info = pm.getActivityInfo(component,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 return info != null;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -445,7 +454,9 @@
             try {
                 IPackageManager pm = AppGlobals.getPackageManager();
                 ActivityInfo info = pm.getActivityInfo(component,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 if (!info.exported) {
                     throw new SecurityException("Cannot launch non-exported components "
                             + component);
@@ -455,7 +466,9 @@
                 // as calling startActivityAsUser ignores the category and just
                 // resolves based on the component if present.
                 List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, user.getIdentifier());
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                        user.getIdentifier());
                 final int size = apps.size();
                 for (int i = 0; i < size; ++i) {
                     ActivityInfo activityInfo = apps.get(i).activityInfo;
@@ -537,7 +550,7 @@
             }
         }
 
-        void postToPackageMonitor(Runnable r) {
+        void postToPackageMonitorHandler(Runnable r) {
             mPackageMonitor.getRegisteredHandler().post(r);
         }
 
@@ -681,7 +694,7 @@
             @Override
             public void onShortcutChanged(@NonNull String packageName,
                     @UserIdInt int userId) {
-                postToPackageMonitor(() -> onShortcutChangedInner(packageName, userId));
+                postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId));
             }
 
             private void onShortcutChangedInner(@NonNull String packageName,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b624087..c2e0992 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -61,10 +61,9 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
-import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
@@ -2565,7 +2564,8 @@
         final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
         } else {
@@ -2580,7 +2580,8 @@
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
         final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
         } else {
@@ -2592,7 +2593,8 @@
         final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
 
         final List<ResolveInfo> matches = queryIntentReceiversInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         ResolveInfo best = null;
         final int N = matches.size();
         for (int i = 0; i < N; i++) {
@@ -2627,7 +2629,8 @@
 
         final Intent resolverIntent = new Intent(Intent.ACTION_RESOLVE_EPHEMERAL_PACKAGE);
         final List<ResolveInfo> resolvers = queryIntentServicesInternal(resolverIntent, null,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
 
         final int N = resolvers.size();
         if (N == 0) {
@@ -2672,7 +2675,8 @@
         intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
 
         final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, PACKAGE_MIME_TYPE,
-                MATCH_SYSTEM_ONLY | MATCH_ENCRYPTION_AWARE_AND_UNAWARE, UserHandle.USER_SYSTEM);
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
         if (matches.size() == 0) {
             return null;
         } else if (matches.size() == 1) {
@@ -2886,8 +2890,8 @@
                 throw new SecurityException("Package " + packageName + " is currently frozen!");
             }
 
-            if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isEncryptionAware()
-                    || ps.pkg.applicationInfo.isPartiallyEncryptionAware())) {
+            if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isDirectBootAware()
+                    || ps.pkg.applicationInfo.isPartiallyDirectBootAware())) {
                 throw new SecurityException("Package " + packageName + " is not encryption aware!");
             }
         }
@@ -3255,17 +3259,17 @@
      * Update given flags based on encryption status of current user.
      */
     private int updateFlags(int flags, int userId) {
-        if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
-                | PackageManager.MATCH_ENCRYPTION_AWARE)) != 0) {
+        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE)) != 0) {
             // Caller expressed an explicit opinion about what encryption
             // aware/unaware components they want to see, so fall through and
             // give them what they want
         } else {
             // Caller expressed no opinion, so match based on user state
             if (isUserKeyUnlocked(userId)) {
-                flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+                flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
             } else {
-                flags |= PackageManager.MATCH_ENCRYPTION_AWARE;
+                flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE;
             }
         }
         return flags;
@@ -3280,8 +3284,8 @@
                 | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS)) != 0) {
             // Caller is asking for component details, so they'd better be
             // asking for specific encryption matching behavior, or be triaged
-            if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
-                    | PackageManager.MATCH_ENCRYPTION_AWARE
+            if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                    | PackageManager.MATCH_DIRECT_BOOT_AWARE
                     | PackageManager.MATCH_DEBUG_TRIAGED_MISSING)) == 0) {
                 triaged = false;
             }
@@ -3318,8 +3322,8 @@
         boolean triaged = true;
         // Caller is asking for component details, so they'd better be
         // asking for specific encryption matching behavior, or be triaged
-        if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
-                | PackageManager.MATCH_ENCRYPTION_AWARE
+        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE
                 | PackageManager.MATCH_DEBUG_TRIAGED_MISSING)) == 0) {
             triaged = false;
         }
@@ -6126,10 +6130,10 @@
                 final PackageParser.Package p = i.next();
                 if (p.applicationInfo == null) continue;
 
-                final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
-                        && !p.applicationInfo.isEncryptionAware();
-                final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
-                        && p.applicationInfo.isEncryptionAware();
+                final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
+                        && !p.applicationInfo.isDirectBootAware();
+                final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
+                        && p.applicationInfo.isDirectBootAware();
 
                 if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
                         && (!mSafeMode || isSystemApp(p))
@@ -8289,8 +8293,8 @@
                 a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
                 a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
                 a.info.dataDir = pkg.applicationInfo.dataDir;
-                a.info.deviceEncryptedDataDir = pkg.applicationInfo.deviceEncryptedDataDir;
-                a.info.credentialEncryptedDataDir = pkg.applicationInfo.credentialEncryptedDataDir;
+                a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
+                a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;
 
                 // TODO: Update instrumentation.nativeLibraryDir as well ? Does it
                 // need other information about the application, like the ABI and what not ?
@@ -16459,10 +16463,22 @@
         return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
     }
 
-    ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
-            int userId) {
+    private Intent getHomeIntent() {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_HOME);
+        return intent;
+    }
+
+    private IntentFilter getHomeFilter() {
+        IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
+        filter.addCategory(Intent.CATEGORY_HOME);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+        return filter;
+    }
+
+    ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+            int userId) {
+        Intent intent  = getHomeIntent();
         List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
                 PackageManager.GET_META_DATA, userId);
         ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
@@ -16481,6 +16497,32 @@
     }
 
     @Override
+    public void setHomeActivity(ComponentName comp, int userId) {
+        ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
+        getHomeActivitiesAsUser(homeActivities, userId);
+
+        boolean found = false;
+
+        final int size = homeActivities.size();
+        final ComponentName[] set = new ComponentName[size];
+        for (int i = 0; i < size; i++) {
+            final ResolveInfo candidate = homeActivities.get(i);
+            final ActivityInfo info = candidate.activityInfo;
+            final ComponentName activityName = new ComponentName(info.packageName, info.name);
+            set[i] = activityName;
+            if (!found && activityName.equals(comp)) {
+                found = true;
+            }
+        }
+        if (!found) {
+            throw new IllegalArgumentException("Component " + comp + " cannot be home on user "
+                    + userId);
+        }
+        replacePreferredActivity(getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY,
+                set, comp, userId);
+    }
+
+    @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
         if (!sUserManager.exists(userId)) return;
@@ -16624,6 +16666,22 @@
         }
     }
 
+    @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        if (!sUserManager.exists(userId)) {
+            return;
+        }
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission*/,
+                false /* checkShell */, "flushPackageRestrictions");
+        synchronized (mPackages) {
+            mSettings.writePackageRestrictionsLPr(userId);
+            mDirtyUsers.remove(userId);
+            if (mDirtyUsers.isEmpty()) {
+                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+            }
+        }
+    }
+
     private void sendPackageChangedBroadcast(String packageName,
             boolean killFlag, ArrayList<String> componentNames, int packageUid) {
         if (DEBUG_INSTALL)
@@ -18332,13 +18390,13 @@
 
     /**
      * For system apps on non-FBE devices, this method migrates any existing
-     * CE/DE data to match the {@code forceDeviceEncrypted} flag requested by
-     * the app.
+     * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag
+     * requested by the app.
      */
     private boolean maybeMigrateAppData(String volumeUuid, int userId, PackageParser.Package pkg) {
         if (pkg.isSystemApp() && !StorageManager.isFileEncryptedNativeOrEmulated()
-                && PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
-            final int storageTarget = pkg.applicationInfo.isForceDeviceEncrypted()
+                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+            final int storageTarget = pkg.applicationInfo.isDefaultToDeviceProtectedStorage()
                     ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
             synchronized (mInstallLock) {
                 try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index d77168c..319fc37 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -117,6 +117,8 @@
                     return runSuspend(true);
                 case "unsuspend":
                     return runSuspend(false);
+                case "set-home-activity":
+                    return runSetHomeActivity();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -963,6 +965,39 @@
         return params;
     }
 
+    private int runSetHomeActivity() {
+        final PrintWriter pw = getOutPrintWriter();
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        String component = getNextArg();
+        ComponentName componentName =
+                component != null ? ComponentName.unflattenFromString(component) : null;
+
+        if (componentName == null) {
+            pw.println("Error: component name not specified or invalid");
+            return 1;
+        }
+
+        try {
+            mInterface.setHomeActivity(componentName, userId);
+            return 0;
+        } catch (RemoteException e) {
+            pw.println(e.toString());
+            return 1;
+        }
+    }
+
     private static String checkAbiArgument(String abi) {
         if (TextUtils.isEmpty(abi)) {
             throw new IllegalArgumentException("Missing ABI argument");
@@ -1303,6 +1338,8 @@
         pw.println("    Suspends the specified package (as user).");
         pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
         pw.println("    Unsuspends the specified package (as user).");
+        pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
+        pw.println("    set the default home activity (aka launcher).");
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4c77f28..e66ec3c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3048,7 +3048,8 @@
             tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), "  ");
         }
         Intent intent = new Intent();
-        int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+        int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
         intent.setAction(tmpPa.getAction(0));
         for (int i=0; i<tmpPa.countCategories(); i++) {
             String cat = tmpPa.getCategory(i);
@@ -4175,10 +4176,10 @@
         ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
         ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
         ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS, "HAS_DOMAIN_URLS",
-        ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED, "FORCE_DEVICE_ENCRYPTED",
-        ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE, "ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE, "DEFAULT_TO_DEVICE_PROTECTED_STORAGE",
+        ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE, "DIRECT_BOOT_AWARE",
         ApplicationInfo.PRIVATE_FLAG_AUTOPLAY, "AUTOPLAY",
-        ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE, "PARTIALLY_ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE, "PARTIALLY_DIRECT_BOOT_AWARE",
         ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
         ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
         ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES, "RESIZEABLE_ACTIVITIES",
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 0641749..e831bb1 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -44,6 +44,7 @@
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -96,20 +97,18 @@
 /**
  * TODO:
  *
- * - Detect when already registered instances are passed to APIs again, which might break
- *   internal bitmap handling.
+ * - Default launcher check does take a few ms.  Worth caching.
  *
  * - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
  *   -> Need to scan all packages when a user starts too.
  *   -> Clear data -> remove all dynamic?  but not the pinned?
  *
- * - Pinned per each launcher package (multiple launchers)
- *
- * - Make save async (should we?)
- *
  * - Scan and remove orphan bitmaps (just in case).
  *
  * - Backup & restore
+ *
+ * - Detect when already registered instances are passed to APIs again, which might break
+ *   internal bitmap handling.
  */
 public class ShortcutService extends IShortcutService.Stub {
     static final String TAG = "ShortcutService";
@@ -138,7 +137,8 @@
     @VisibleForTesting
     static final int DEFAULT_ICON_PERSIST_QUALITY = 100;
 
-    private static final int SAVE_DELAY_MS = 5000; // in milliseconds.
+    @VisibleForTesting
+    static final int DEFAULT_SAVE_DELAY_MS = 3000;
 
     @VisibleForTesting
     static final String FILENAME_BASE_STATE = "shortcut_service.xml";
@@ -151,33 +151,19 @@
 
     static final String DIRECTORY_BITMAPS = "bitmaps";
 
-    static final String TAG_ROOT = "root";
-    static final String TAG_USER = "user";
-    static final String TAG_PACKAGE = "package";
-    static final String TAG_LAST_RESET_TIME = "last_reset_time";
-    static final String TAG_INTENT_EXTRAS = "intent-extras";
-    static final String TAG_EXTRAS = "extras";
-    static final String TAG_SHORTCUT = "shortcut";
-    static final String TAG_LAUNCHER = "launcher";
+    private static final String TAG_ROOT = "root";
+    private static final String TAG_LAST_RESET_TIME = "last_reset_time";
 
-    static final String ATTR_VALUE = "value";
-    static final String ATTR_NAME = "name";
-    static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
-    static final String ATTR_CALL_COUNT = "call-count";
-    static final String ATTR_LAST_RESET = "last-reset";
-    static final String ATTR_ID = "id";
-    static final String ATTR_ACTIVITY = "activity";
-    static final String ATTR_TITLE = "title";
-    static final String ATTR_INTENT = "intent";
-    static final String ATTR_WEIGHT = "weight";
-    static final String ATTR_TIMESTAMP = "timestamp";
-    static final String ATTR_FLAGS = "flags";
-    static final String ATTR_ICON_RES = "icon-res";
-    static final String ATTR_BITMAP_PATH = "bitmap-path";
+    private static final String ATTR_VALUE = "value";
 
     @VisibleForTesting
     interface ConfigConstants {
         /**
+         * Key name for the save delay, in milliseconds. (int)
+         */
+        String KEY_SAVE_DELAY_MILLIS = "save_delay_ms";
+
+        /**
          * Key name for the throttling reset interval, in seconds. (long)
          */
         String KEY_RESET_INTERVAL_SEC = "reset_interval_sec";
@@ -254,12 +240,22 @@
     private CompressFormat mIconPersistFormat;
     private int mIconPersistQuality;
 
+    private int mSaveDelayMillis;
+
     private final PackageManagerInternal mPackageManagerInternal;
 
+    @GuardedBy("mLock")
+    private List<Integer> mDirtyUserIds = new ArrayList<>();
+
     public ShortcutService(Context context) {
+        this(context, BackgroundThread.get().getLooper());
+    }
+
+    @VisibleForTesting
+    ShortcutService(Context context, Looper looper) {
         mContext = Preconditions.checkNotNull(context);
         LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
-        mHandler = new Handler(BackgroundThread.get().getLooper());
+        mHandler = new Handler(looper);
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
     }
 
@@ -287,7 +283,7 @@
         @Override
         public void onCleanupUser(int userHandle) {
             synchronized (mService.mLock) {
-                mService.onCleanupUserInner(userHandle);
+                mService.onCleanupUserLocked(userHandle);
             }
         }
 
@@ -318,7 +314,10 @@
     }
 
     /** lifecycle event */
-    void onCleanupUserInner(int userId) {
+    void onCleanupUserLocked(int userId) {
+        // Save all dirty information.
+        saveDirtyInfo();
+
         // Unload
         mUsers.delete(userId);
     }
@@ -364,6 +363,9 @@
             result = false;
         }
 
+        mSaveDelayMillis = (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS,
+                DEFAULT_SAVE_DELAY_MS);
+
         mResetInterval = parser.getLong(
                 ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
                 * 1000L;
@@ -505,7 +507,7 @@
     void saveBaseStateLocked() {
         final AtomicFile file = getBaseStateFile();
         if (DEBUG) {
-            Slog.i(TAG, "Saving to " + file.getBaseFile());
+            Slog.d(TAG, "Saving to " + file.getBaseFile());
         }
 
         FileOutputStream outs = null;
@@ -538,7 +540,7 @@
 
         final AtomicFile file = getBaseStateFile();
         if (DEBUG) {
-            Slog.i(TAG, "Loading from " + file.getBaseFile());
+            Slog.d(TAG, "Loading from " + file.getBaseFile());
         }
         try (FileInputStream in = file.openRead()) {
             XmlPullParser parser = Xml.newPullParser();
@@ -583,7 +585,7 @@
     private void saveUserLocked(@UserIdInt int userId) {
         final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
         if (DEBUG) {
-            Slog.i(TAG, "Saving to " + path);
+            Slog.d(TAG, "Saving to " + path);
         }
         path.mkdirs();
         final AtomicFile file = new AtomicFile(path);
@@ -616,7 +618,7 @@
     private UserShortcuts loadUserLocked(@UserIdInt int userId) {
         final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
         if (DEBUG) {
-            Slog.i(TAG, "Loading from " + path);
+            Slog.d(TAG, "Loading from " + path);
         }
         final AtomicFile file = new AtomicFile(path);
 
@@ -625,7 +627,7 @@
             in = file.openRead();
         } catch (FileNotFoundException e) {
             if (DEBUG) {
-                Slog.i(TAG, "Not found " + path);
+                Slog.d(TAG, "Not found " + path);
             }
             return null;
         }
@@ -646,7 +648,7 @@
                     Slog.d(TAG, String.format("depth=%d type=%d name=%s",
                             depth, type, tag));
                 }
-                if ((depth == 1) && TAG_USER.equals(tag)) {
+                if ((depth == 1) && UserShortcuts.TAG_ROOT.equals(tag)) {
                     ret = UserShortcuts.loadFromXml(parser, userId);
                     continue;
                 }
@@ -661,29 +663,58 @@
         }
     }
 
-    // TODO Actually make it async.
     private void scheduleSaveBaseState() {
-        synchronized (mLock) {
-            saveBaseStateLocked();
-        }
+        scheduleSave(UserHandle.USER_NULL); // Special case -- use USER_NULL for base state.
     }
 
-    // TODO Actually make it async.
     void scheduleSaveUser(@UserIdInt int userId) {
+        scheduleSave(userId);
+    }
+
+    // In order to re-schedule, we need to reuse the same instance, so keep it in final.
+    private final Runnable mSaveDirtyInfoRunner = this::saveDirtyInfo;
+
+    private void scheduleSave(@UserIdInt int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "Scheduling to save for " + userId);
+        }
         synchronized (mLock) {
-            saveUserLocked(userId);
+            if (!mDirtyUserIds.contains(userId)) {
+                mDirtyUserIds.add(userId);
+            }
+        }
+        // If already scheduled, remove that and re-schedule in N seconds.
+        mHandler.removeCallbacks(mSaveDirtyInfoRunner);
+        mHandler.postDelayed(mSaveDirtyInfoRunner, mSaveDelayMillis);
+    }
+
+    @VisibleForTesting
+    void saveDirtyInfo() {
+        if (DEBUG) {
+            Slog.d(TAG, "saveDirtyInfo");
+        }
+        synchronized (mLock) {
+            for (int i = mDirtyUserIds.size() - 1; i >= 0; i--) {
+                final int userId = mDirtyUserIds.get(i);
+                if (userId == UserHandle.USER_NULL) { // USER_NULL for base state.
+                    saveBaseStateLocked();
+                } else {
+                    saveUserLocked(userId);
+                }
+            }
+            mDirtyUserIds.clear();
         }
     }
 
     /** Return the last reset time. */
     long getLastResetTimeLocked() {
-        updateTimes();
+        updateTimesLocked();
         return mRawLastResetTime;
     }
 
     /** Return the next reset time. */
     long getNextResetTimeLocked() {
-        updateTimes();
+        updateTimesLocked();
         return mRawLastResetTime + mResetInterval;
     }
 
@@ -694,7 +725,7 @@
     /**
      * Update the last reset time.
      */
-    private void updateTimes() {
+    private void updateTimesLocked() {
 
         final long now = injectCurrentTimeMillis();
 
@@ -706,13 +737,14 @@
         } else if (now < mRawLastResetTime) {
             // Clock rewound.
             if (isClockValid(now)) {
+                Slog.w(TAG, "Clock rewound");
                 // TODO Randomize??
                 mRawLastResetTime = now;
             }
         } else {
-            // TODO Do it properly.
-            while ((mRawLastResetTime + mResetInterval) <= now) {
-                mRawLastResetTime += mResetInterval;
+            if ((mRawLastResetTime + mResetInterval) <= now) {
+                final long offset = mRawLastResetTime % mResetInterval;
+                mRawLastResetTime = ((now / mResetInterval) * mResetInterval) + offset;
             }
         }
         if (prevLastResetTime != mRawLastResetTime) {
@@ -723,7 +755,7 @@
     /** Return the per-user state. */
     @GuardedBy("mLock")
     @NonNull
-    private UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) {
+    UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) {
         UserShortcuts userPackages = mUsers.get(userId);
         if (userPackages == null) {
             userPackages = loadUserLocked(userId);
@@ -738,15 +770,16 @@
     /** Return the per-user per-package state. */
     @GuardedBy("mLock")
     @NonNull
-    private PackageShortcuts getPackageShortcutsLocked(
+    PackageShortcuts getPackageShortcutsLocked(
             @NonNull String packageName, @UserIdInt int userId) {
-        final UserShortcuts userPackages = getUserShortcutsLocked(userId);
-        PackageShortcuts shortcuts = userPackages.getPackages().get(packageName);
-        if (shortcuts == null) {
-            shortcuts = new PackageShortcuts(userId, packageName);
-            userPackages.getPackages().put(packageName, shortcuts);
-        }
-        return shortcuts;
+        return getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
+    }
+
+    @GuardedBy("mLock")
+    @NonNull
+    LauncherShortcuts getLauncherShortcuts(
+            @NonNull String packageName, @UserIdInt int userId) {
+        return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName);
     }
 
     // === Caller validation ===
@@ -981,12 +1014,11 @@
     // Test overrides it.
     int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
         try {
-
-            // TODO Is MATCH_UNINSTALLED_PACKAGES correct to get SD card app info?
-
             return mContext.getPackageManager().getPackageUidAsUser(packageName,
-                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                            | PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                            | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                    userId);
         } catch (NameNotFoundException e) {
             return -1;
         }
@@ -1057,7 +1089,7 @@
         validatePersistableBundleForXml(shortcut.getIntentPersistableExtras());
         validatePersistableBundleForXml(shortcut.getExtras());
 
-        shortcut.setFlags(0);
+        shortcut.replaceFlags(0);
     }
 
     // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those
@@ -1129,8 +1161,7 @@
             // Then, add/update all.  We need to make sure to take over "pinned" flag.
             for (int i = 0; i < size; i++) {
                 final ShortcutInfo newShortcut = newShortcuts.get(i);
-                newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
-                ps.updateShortcutWithCapping(this, newShortcut);
+                ps.addDynamicShortcut(this, newShortcut);
             }
         }
         userPackageChanged(packageName, userId);
@@ -1194,8 +1225,7 @@
             fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
 
             // Add it.
-            newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
-            ps.updateShortcutWithCapping(this, newShortcut);
+            ps.addDynamicShortcut(this, newShortcut);
         }
         userPackageChanged(packageName, userId);
 
@@ -1251,7 +1281,8 @@
 
         final ArrayList<ShortcutInfo> ret = new ArrayList<>();
 
-        getPackageShortcutsLocked(packageName, userId).findAll(ret, query, cloneFlags);
+        getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags,
+                /* callingLauncher= */ null);
 
         return new ParceledListSlice<>(ret);
     }
@@ -1406,25 +1437,27 @@
 
             synchronized (mLock) {
                 if (packageName != null) {
-                    getShortcutsInnerLocked(packageName, changedSince, componentName, queryFlags,
-                            userId, ret, cloneFlag);
+                    getShortcutsInnerLocked(
+                            callingPackage, packageName, changedSince,
+                            componentName, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final ArrayMap<String, PackageShortcuts> packages =
                             getUserShortcutsLocked(userId).getPackages();
                     for (int i = packages.size() - 1; i >= 0; i--) {
                         getShortcutsInnerLocked(
-                                packages.keyAt(i),
-                                changedSince, componentName, queryFlags, userId, ret, cloneFlag);
+                                callingPackage, packages.keyAt(i), changedSince,
+                                componentName, queryFlags, userId, ret, cloneFlag);
                     }
                 }
             }
             return ret;
         }
 
-        private void getShortcutsInnerLocked(@Nullable String packageName,long changedSince,
+        private void getShortcutsInnerLocked(@NonNull String callingPackage,
+                @Nullable String packageName,long changedSince,
                 @Nullable ComponentName componentName, int queryFlags,
                 int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
-            getPackageShortcutsLocked(packageName, userId).findAll(ret,
+            getPackageShortcutsLocked(packageName, userId).findAll(ShortcutService.this, ret,
                     (ShortcutInfo si) -> {
                         if (si.getLastChangedTimestamp() < changedSince) {
                             return false;
@@ -1435,12 +1468,12 @@
                         }
                         final boolean matchDynamic =
                                 ((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
-                                && si.isDynamic();
+                                        && si.isDynamic();
                         final boolean matchPinned =
                                 ((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
                                         && si.isPinned();
                         return matchDynamic || matchPinned;
-                    }, cloneFlag);
+                    }, cloneFlag, callingPackage);
         }
 
         @Override
@@ -1453,9 +1486,10 @@
             final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
             final ArraySet<String> idSet = new ArraySet<>(ids);
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).findAll(ret,
+                getPackageShortcutsLocked(packageName, userId).findAll(
+                        ShortcutService.this, ret,
                         (ShortcutInfo si) -> idSet.contains(si.getId()),
-                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage);
             }
             return ret;
         }
@@ -1468,8 +1502,8 @@
             Preconditions.checkNotNull(shortcutIds, "shortcutIds");
 
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).replacePinned(
-                        ShortcutService.this, callingPackage, shortcutIds);
+                getLauncherShortcuts(callingPackage, userId).pinShortcuts(
+                        ShortcutService.this, packageName, shortcutIds);
             }
             userPackageChanged(packageName, userId);
         }
@@ -1812,6 +1846,14 @@
         Binder.restoreCallingIdentity(token);
     }
 
+    final void wtf(String message) {
+        Slog.wtf(TAG, message, /* exception= */ null);
+    }
+
+    void wtf(String message, Exception e) {
+        Slog.wtf(TAG, message, e);
+    }
+
     File injectSystemDataPath() {
         return Environment.getDataSystemDirectory();
     }
@@ -1882,11 +1924,18 @@
 class UserShortcuts {
     private static final String TAG = ShortcutService.TAG;
 
+    static final String TAG_ROOT = "user";
+    private static final String TAG_LAUNCHER = "launcher";
+
+    private static final String ATTR_VALUE = "value";
+
     @UserIdInt
     final int mUserId;
 
     private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
 
+    private final ArrayMap<String, LauncherShortcuts> mLaunchers = new ArrayMap<>();
+
     private ComponentName mLauncherComponent;
 
     public UserShortcuts(int userId) {
@@ -1897,17 +1946,45 @@
         return mPackages;
     }
 
-    public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
-        out.startTag(null, ShortcutService.TAG_USER);
+    public ArrayMap<String, LauncherShortcuts> getLaunchers() {
+        return mLaunchers;
+    }
 
-        ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER,
+    public PackageShortcuts getPackageShortcuts(@NonNull String packageName) {
+        PackageShortcuts ret = mPackages.get(packageName);
+        if (ret == null) {
+            ret = new PackageShortcuts(mUserId, packageName);
+            mPackages.put(packageName, ret);
+        }
+        return ret;
+    }
+
+    public LauncherShortcuts getLauncherShortcuts(@NonNull String packageName) {
+        LauncherShortcuts ret = mLaunchers.get(packageName);
+        if (ret == null) {
+            ret = new LauncherShortcuts(mUserId, packageName);
+            mLaunchers.put(packageName, ret);
+        }
+        return ret;
+    }
+
+    public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
+        out.startTag(null, TAG_ROOT);
+
+        ShortcutService.writeTagValue(out, TAG_LAUNCHER,
                 mLauncherComponent);
 
-        for (int i = 0; i < mPackages.size(); i++) {
+        final int lsize = mLaunchers.size();
+        for (int i = 0; i < lsize; i++) {
+            mLaunchers.valueAt(i).saveToXml(out);
+        }
+
+        final int psize = mPackages.size();
+        for (int i = 0; i < psize; i++) {
             mPackages.valueAt(i).saveToXml(out);
         }
 
-        out.endTag(null, ShortcutService.TAG_USER);
+        out.endTag(null, TAG_ROOT);
     }
 
     public static UserShortcuts loadFromXml(XmlPullParser parser, int userId)
@@ -1924,16 +2001,26 @@
             final int depth = parser.getDepth();
             final String tag = parser.getName();
             switch (tag) {
-                case ShortcutService.TAG_LAUNCHER:
+                case TAG_LAUNCHER: {
                     ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
-                            parser, ShortcutService.ATTR_VALUE);
+                            parser, ATTR_VALUE);
                     continue;
-                case ShortcutService.TAG_PACKAGE:
+                }
+                case PackageShortcuts.TAG_ROOT: {
                     final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId);
 
                     // Don't use addShortcut(), we don't need to save the icon.
                     ret.getPackages().put(shortcuts.mPackageName, shortcuts);
                     continue;
+                }
+
+                case LauncherShortcuts.TAG_ROOT: {
+                    final LauncherShortcuts shortcuts =
+                            LauncherShortcuts.loadFromXml(parser, userId);
+
+                    ret.getLaunchers().put(shortcuts.mPackageName, shortcuts);
+                    continue;
+                }
             }
             throw ShortcutService.throwForInvalidTag(depth, tag);
         }
@@ -1970,18 +2057,199 @@
         pw.print(mLauncherComponent);
         pw.println();
 
+        for (int i = 0; i < mLaunchers.size(); i++) {
+            mLaunchers.valueAt(i).dump(s, pw, prefix + "  ");
+        }
+
         for (int i = 0; i < mPackages.size(); i++) {
             mPackages.valueAt(i).dump(s, pw, prefix + "  ");
         }
     }
 }
 
+class LauncherShortcuts {
+    private static final String TAG = ShortcutService.TAG;
+
+    static final String TAG_ROOT = "launcher-pins";
+
+    private static final String TAG_PACKAGE = "package";
+    private static final String TAG_PIN = "pin";
+
+    private static final String ATTR_VALUE = "value";
+    private static final String ATTR_PACKAGE_NAME = "package-name";
+
+    @UserIdInt
+    final int mUserId;
+
+    @NonNull
+    final String mPackageName;
+
+    /**
+     * Package name -> IDs.
+     */
+    final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
+
+    LauncherShortcuts(@UserIdInt int userId, @NonNull String packageName) {
+        mUserId = userId;
+        mPackageName = packageName;
+    }
+
+    public void pinShortcuts(@NonNull ShortcutService s, @NonNull String packageName,
+            @NonNull List<String> ids) {
+        final int idSize = ids.size();
+        if (idSize == 0) {
+            mPinnedShortcuts.remove(packageName);
+        } else {
+            final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
+
+            // Pin shortcuts.  Make sure only pin the ones that were visible to the caller.
+            // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
+
+            final PackageShortcuts packageShortcuts =
+                    s.getPackageShortcutsLocked(packageName, mUserId);
+            final ArraySet<String> newSet = new ArraySet<>();
+
+            for (int i = 0; i < idSize; i++) {
+                final String id = ids.get(i);
+                final ShortcutInfo si = packageShortcuts.findShortcutById(id);
+                if (si == null) {
+                    continue;
+                }
+                if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
+                    newSet.add(id);
+                }
+            }
+            mPinnedShortcuts.put(packageName, newSet);
+        }
+        s.getPackageShortcutsLocked(packageName, mUserId).refreshPinnedFlags(s);
+    }
+
+    /**
+     * Return the pinned shortcut IDs for the publisher package.
+     */
+    public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
+        return mPinnedShortcuts.get(packageName);
+    }
+
+    /**
+     * Persist.
+     */
+    public void saveToXml(XmlSerializer out) throws IOException {
+        out.startTag(null, TAG_ROOT);
+        ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
+                mPackageName);
+
+        final int size = mPinnedShortcuts.size();
+        for (int i = 0; i < size; i++) {
+            out.startTag(null, TAG_PACKAGE);
+            ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
+                    mPinnedShortcuts.keyAt(i));
+
+            final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+            final int idSize = ids.size();
+            for (int j = 0; j < idSize; j++) {
+                ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j));
+            }
+            out.endTag(null, TAG_PACKAGE);
+        }
+
+        out.endTag(null, TAG_ROOT);
+    }
+
+    /**
+     * Load.
+     */
+    public static LauncherShortcuts loadFromXml(XmlPullParser parser, int userId)
+            throws IOException, XmlPullParserException {
+        final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
+                ATTR_PACKAGE_NAME);
+
+        final LauncherShortcuts ret = new LauncherShortcuts(userId, launcherPackageName);
+
+        ArraySet<String> ids = null;
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            switch (tag) {
+                case TAG_PACKAGE: {
+                    final String packageName = ShortcutService.parseStringAttribute(parser,
+                            ATTR_PACKAGE_NAME);
+                    ids = new ArraySet<>();
+                    ret.mPinnedShortcuts.put(packageName, ids);
+                    continue;
+                }
+                case TAG_PIN: {
+                    ids.add(ShortcutService.parseStringAttribute(parser,
+                            ATTR_VALUE));
+                    continue;
+                }
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return ret;
+    }
+
+    public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.println();
+
+        pw.print(prefix);
+        pw.print("Launcher: ");
+        pw.print(mPackageName);
+        pw.println();
+
+        final int size = mPinnedShortcuts.size();
+        for (int i = 0; i < size; i++) {
+            pw.println();
+
+            pw.print(prefix);
+            pw.print("  ");
+            pw.print("Package: ");
+            pw.println(mPinnedShortcuts.keyAt(i));
+
+            final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+            final int idSize = ids.size();
+
+            for (int j = 0; j < idSize; j++) {
+                pw.print(prefix);
+                pw.print("    ");
+                pw.print(ids.valueAt(j));
+                pw.println();
+            }
+        }
+    }
+}
+
 /**
  * All the information relevant to shortcuts from a single package (per-user).
  */
 class PackageShortcuts {
     private static final String TAG = ShortcutService.TAG;
 
+    static final String TAG_ROOT = "package";
+    private static final String TAG_INTENT_EXTRAS = "intent-extras";
+    private static final String TAG_EXTRAS = "extras";
+    private static final String TAG_SHORTCUT = "shortcut";
+
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
+    private static final String ATTR_CALL_COUNT = "call-count";
+    private static final String ATTR_LAST_RESET = "last-reset";
+    private static final String ATTR_ID = "id";
+    private static final String ATTR_ACTIVITY = "activity";
+    private static final String ATTR_TITLE = "title";
+    private static final String ATTR_INTENT = "intent";
+    private static final String ATTR_WEIGHT = "weight";
+    private static final String ATTR_TIMESTAMP = "timestamp";
+    private static final String ATTR_FLAGS = "flags";
+    private static final String ATTR_ICON_RES = "icon-res";
+    private static final String ATTR_BITMAP_PATH = "bitmap-path";
+
     @UserIdInt
     final int mUserId;
 
@@ -2039,27 +2307,34 @@
      *
      * It checks the max number of dynamic shortcuts.
      */
-    public void updateShortcutWithCapping(@NonNull ShortcutService s,
+    public void addDynamicShortcut(@NonNull ShortcutService s,
             @NonNull ShortcutInfo newShortcut) {
+        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
 
-        int oldFlags = 0;
-        int newDynamicCount = mDynamicShortcutCount;
+        final boolean wasPinned;
+        final int newDynamicCount;
 
-        if (oldShortcut != null) {
-            oldFlags = oldShortcut.getFlags();
+        if (oldShortcut == null) {
+            wasPinned = false;
+            newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
+        } else {
+            wasPinned = oldShortcut.isPinned();
             if (oldShortcut.isDynamic()) {
-                newDynamicCount--;
+                newDynamicCount = mDynamicShortcutCount; // not adding a dynamic shortcut.
+            } else {
+                newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
             }
         }
-        if (newShortcut.isDynamic()) {
-            newDynamicCount++;
-        }
+
         // Make sure there's still room.
         s.enforceMaxDynamicShortcuts(newDynamicCount);
 
         // Okay, make it dynamic and add.
-        newShortcut.addFlags(oldFlags);
+        if (wasPinned) {
+            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+        }
 
         addShortcut(s, newShortcut);
         mDynamicShortcutCount = newDynamicCount;
@@ -2088,6 +2363,9 @@
         }
     }
 
+    /**
+     * Remove all dynamic shortcuts.
+     */
     public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -2096,6 +2374,9 @@
         mDynamicShortcutCount = 0;
     }
 
+    /**
+     * Remove a dynamic shortcut by ID.
+     */
     public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
         final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
 
@@ -2112,24 +2393,40 @@
         }
     }
 
-    public void replacePinned(@NonNull ShortcutService s, String launcherPackage,
-            List<String> shortcutIds) {
-
-        // TODO Should be per launcherPackage.
-
+    /**
+     * Called after a launcher updates the pinned set.  For each shortcut in this package,
+     * set FLAG_PINNED if any launcher has pinned it.  Otherwise, clear it.
+     *
+     * <p>Then remove all shortcuts that are not dynamic and no longer pinned either.
+     */
+    public void refreshPinnedFlags(@NonNull ShortcutService s) {
         // First, un-pin all shortcuts
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
         }
 
-        // Then pin ALL
-        for (int i = shortcutIds.size() - 1; i >= 0; i--) {
-            final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i));
-            if (shortcut != null) {
-                shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+        // Then, for the pinned set for each launcher, set the pin flag one by one.
+        final ArrayMap<String, LauncherShortcuts> launchers =
+                s.getUserShortcutsLocked(mUserId).getLaunchers();
+
+        for (int l = launchers.size() - 1; l >= 0; l--) {
+            final LauncherShortcuts launcherShortcuts = launchers.valueAt(l);
+            final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(mPackageName);
+
+            if (pinned == null || pinned.size() == 0) {
+                continue;
+            }
+            for (int i = pinned.size() - 1; i >= 0; i--) {
+                final ShortcutInfo si = mShortcuts.get(pinned.valueAt(i));
+                if (si == null) {
+                    s.wtf("Shortcut not found");
+                } else {
+                    si.addFlags(ShortcutInfo.FLAG_PINNED);
+                }
             }
         }
 
+        // Lastly, remove the ones that are no longer pinned nor dynamic.
         removeOrphans(s);
     }
 
@@ -2141,12 +2438,19 @@
 
         final long now = s.injectCurrentTimeMillis();
         if (ShortcutService.isClockValid(now) && mLastResetTime > now) {
-            // Clock rewound. // TODO Test it
+            Slog.w(TAG, "Clock rewound");
+            // Clock rewound.
             mLastResetTime = now;
+            mApiCallCount = 0;
+            return mApiCallCount;
         }
 
         // If not reset yet, then reset.
         if (mLastResetTime < last) {
+            if (ShortcutService.DEBUG) {
+                Slog.d(TAG, String.format("My last reset=%d, now=%d, last=%d: resetting",
+                        mLastResetTime, now, last));
+            }
             mApiCallCount = 0;
             mLastResetTime = last;
         }
@@ -2173,12 +2477,40 @@
     /**
      * Find all shortcuts that match {@code query}.
      */
-    public void findAll(@NonNull List<ShortcutInfo> result,
-            @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
+    public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
+            @Nullable Predicate<ShortcutInfo> query, int cloneFlag,
+            @Nullable String callingLauncher) {
+
+        // Set of pinned shortcuts by the calling launcher.
+        final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
+                : s.getLauncherShortcuts(callingLauncher, mUserId)
+                    .getPinnedShortcutIds(mPackageName);
+
         for (int i = 0; i < mShortcuts.size(); i++) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (query == null || query.test(si)) {
-                result.add(si.clone(cloneFlag));
+
+            // If it's called by non-launcher (i.e. publisher, always include -> true.
+            // Otherwise, only include non-dynamic pinned one, if the calling launcher has pinned
+            // it.
+            final boolean isPinnedByCaller = (callingLauncher == null)
+                    || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
+            if (!si.isDynamic()) {
+                if (!si.isPinned()) {
+                    s.wtf("Shortcut not pinned here");
+                    continue;
+                }
+                if (!isPinnedByCaller) {
+                    continue;
+                }
+            }
+            final ShortcutInfo clone = si.clone(cloneFlag);
+            // Fix up isPinned for the caller.  Note we need to do it before the "test" callback,
+            // since it may check isPinned.
+            if (!isPinnedByCaller) {
+                clone.clearFlags(ShortcutInfo.FLAG_PINNED);
+            }
+            if (query == null || query.test(clone)) {
+                result.add(clone);
             }
         }
     }
@@ -2188,6 +2520,8 @@
     }
 
     public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.println();
+
         pw.print(prefix);
         pw.print("Package: ");
         pw.print(mPackageName);
@@ -2235,58 +2569,58 @@
     }
 
     public void saveToXml(@NonNull XmlSerializer out) throws IOException, XmlPullParserException {
-        out.startTag(null, ShortcutService.TAG_PACKAGE);
+        out.startTag(null, TAG_ROOT);
 
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_NAME, mPackageName);
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_CALL_COUNT, mApiCallCount);
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_LAST_RESET, mLastResetTime);
+        ShortcutService.writeAttr(out, ATTR_NAME, mPackageName);
+        ShortcutService.writeAttr(out, ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
+        ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
+        ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
 
         final int size = mShortcuts.size();
         for (int j = 0; j < size; j++) {
             saveShortcut(out, mShortcuts.valueAt(j));
         }
 
-        out.endTag(null, ShortcutService.TAG_PACKAGE);
+        out.endTag(null, TAG_ROOT);
     }
 
     private static void saveShortcut(XmlSerializer out, ShortcutInfo si)
             throws IOException, XmlPullParserException {
-        out.startTag(null, ShortcutService.TAG_SHORTCUT);
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_ID, si.getId());
+        out.startTag(null, TAG_SHORTCUT);
+        ShortcutService.writeAttr(out, ATTR_ID, si.getId());
         // writeAttr(out, "package", si.getPackageName()); // not needed
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_ACTIVITY, si.getActivityComponent());
+        ShortcutService.writeAttr(out, ATTR_ACTIVITY, si.getActivityComponent());
         // writeAttr(out, "icon", si.getIcon());  // We don't save it.
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_TITLE, si.getTitle());
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_INTENT, si.getIntentNoExtras());
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_WEIGHT, si.getWeight());
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_TIMESTAMP,
+        ShortcutService.writeAttr(out, ATTR_TITLE, si.getTitle());
+        ShortcutService.writeAttr(out, ATTR_INTENT, si.getIntentNoExtras());
+        ShortcutService.writeAttr(out, ATTR_WEIGHT, si.getWeight());
+        ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
                 si.getLastChangedTimestamp());
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_FLAGS, si.getFlags());
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_ICON_RES, si.getIconResourceId());
-        ShortcutService.writeAttr(out, ShortcutService.ATTR_BITMAP_PATH, si.getBitmapPath());
+        ShortcutService.writeAttr(out, ATTR_FLAGS, si.getFlags());
+        ShortcutService.writeAttr(out, ATTR_ICON_RES, si.getIconResourceId());
+        ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
 
-        ShortcutService.writeTagExtra(out, ShortcutService.TAG_INTENT_EXTRAS,
+        ShortcutService.writeTagExtra(out, TAG_INTENT_EXTRAS,
                 si.getIntentPersistableExtras());
-        ShortcutService.writeTagExtra(out, ShortcutService.TAG_EXTRAS, si.getExtras());
+        ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
 
-        out.endTag(null, ShortcutService.TAG_SHORTCUT);
+        out.endTag(null, TAG_SHORTCUT);
     }
 
     public static PackageShortcuts loadFromXml(XmlPullParser parser, int userId)
             throws IOException, XmlPullParserException {
 
         final String packageName = ShortcutService.parseStringAttribute(parser,
-                ShortcutService.ATTR_NAME);
+                ATTR_NAME);
 
         final PackageShortcuts ret = new PackageShortcuts(userId, packageName);
 
         ret.mDynamicShortcutCount =
-                ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_DYNAMIC_COUNT);
+                ShortcutService.parseIntAttribute(parser, ATTR_DYNAMIC_COUNT);
         ret.mApiCallCount =
-                ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_CALL_COUNT);
+                ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
         ret.mLastResetTime =
-                ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_LAST_RESET);
+                ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
 
         final int outerDepth = parser.getDepth();
         int type;
@@ -2298,7 +2632,7 @@
             final int depth = parser.getDepth();
             final String tag = parser.getName();
             switch (tag) {
-                case ShortcutService.TAG_SHORTCUT:
+                case TAG_SHORTCUT:
                     final ShortcutInfo si = parseShortcut(parser, packageName);
 
                     // Don't use addShortcut(), we don't need to save the icon.
@@ -2325,17 +2659,17 @@
         int iconRes;
         String bitmapPath;
 
-        id = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_ID);
+        id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
         activityComponent = ShortcutService.parseComponentNameAttribute(parser,
-                ShortcutService.ATTR_ACTIVITY);
-        title = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_TITLE);
-        intent = ShortcutService.parseIntentAttribute(parser, ShortcutService.ATTR_INTENT);
-        weight = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_WEIGHT);
+                ATTR_ACTIVITY);
+        title = ShortcutService.parseStringAttribute(parser, ATTR_TITLE);
+        intent = ShortcutService.parseIntentAttribute(parser, ATTR_INTENT);
+        weight = (int) ShortcutService.parseLongAttribute(parser, ATTR_WEIGHT);
         lastChangedTimestamp = (int) ShortcutService.parseLongAttribute(parser,
-                ShortcutService.ATTR_TIMESTAMP);
-        flags = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_FLAGS);
-        iconRes = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_ICON_RES);
-        bitmapPath = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_BITMAP_PATH);
+                ATTR_TIMESTAMP);
+        flags = (int) ShortcutService.parseLongAttribute(parser, ATTR_FLAGS);
+        iconRes = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES);
+        bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
 
         final int outerDepth = parser.getDepth();
         int type;
@@ -2351,10 +2685,10 @@
                         depth, type, tag));
             }
             switch (tag) {
-                case ShortcutService.TAG_INTENT_EXTRAS:
+                case TAG_INTENT_EXTRAS:
                     intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
                     continue;
-                case ShortcutService.TAG_EXTRAS:
+                case TAG_EXTRAS:
                     extras = PersistableBundle.restoreFromXml(parser);
                     continue;
             }
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index 57ae523..a47f250 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -138,16 +138,18 @@
                     ComponentName componentName = new ComponentName(packageName, className);
                     try {
                         info = packageManager.getActivityInfo(componentName,
-                                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                                | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                        | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                     } catch (PackageManager.NameNotFoundException e) {
                         String[] packages = packageManager.canonicalToCurrentPackageNames(
                                 new String[] { packageName });
                         componentName = new ComponentName(packages[0], className);
                         try {
                             info = packageManager.getActivityInfo(componentName,
-                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                                    | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                            | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                         } catch (PackageManager.NameNotFoundException e1) {
                             Log.w(TAG, "Unable to add bookmark: " + packageName
                                     + "/" + className, e);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 91d8671..cbd77d4 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.power;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -74,6 +75,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -162,6 +165,14 @@
     // Default setting for double tap to wake.
     private static final int DEFAULT_DOUBLE_TAP_TO_WAKE = 0;
 
+    /** Constants for {@link #shutdownOrRebootInternal} */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({HALT_MODE_SHUTDOWN, HALT_MODE_REBOOT, HALT_MODE_REBOOT_SAFE_MODE})
+    public @interface HaltMode {}
+    private static final int HALT_MODE_SHUTDOWN = 0;
+    private static final int HALT_MODE_REBOOT = 1;
+    private static final int HALT_MODE_REBOOT_SAFE_MODE = 2;
+
     private final Context mContext;
     private final ServiceThread mHandlerThread;
     private final PowerManagerHandler mHandler;
@@ -2392,7 +2403,7 @@
         updatePowerStateLocked();
     }
 
-    private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
+    private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
             final String reason, boolean wait) {
         if (mHandler == null || !mSystemReady) {
             throw new IllegalStateException("Too early to call shutdown() or reboot()");
@@ -2402,10 +2413,12 @@
             @Override
             public void run() {
                 synchronized (this) {
-                    if (shutdown) {
-                        ShutdownThread.shutdown(mContext, reason, confirm);
-                    } else {
+                    if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
+                        ShutdownThread.rebootSafeMode(mContext, confirm);
+                    } else if (haltMode == HALT_MODE_REBOOT) {
                         ShutdownThread.reboot(mContext, reason, confirm);
+                    } else {
+                        ShutdownThread.shutdown(mContext, reason, confirm);
                     }
                 }
             }
@@ -3465,7 +3478,26 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                shutdownOrRebootInternal(false, confirm, reason, wait);
+                shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        /**
+         * Reboots the device into safe mode
+         *
+         * @param confirm If true, shows a reboot confirmation dialog.
+         * @param wait If true, this call waits for the reboot to complete and does not return.
+         */
+        @Override // Binder call
+        public void rebootSafeMode(boolean confirm, boolean wait) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm,
+                        PowerManager.REBOOT_SAFE_MODE, wait);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -3483,7 +3515,7 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                shutdownOrRebootInternal(true, confirm, reason, wait);
+                shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 2db6b5d..50699f8 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -35,14 +35,14 @@
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.Slog;
 import android.webkit.IWebViewUpdateService;
+import android.webkit.WebViewFactory;
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
-import android.webkit.WebViewFactory;
 
 import com.android.server.SystemService;
 
@@ -66,8 +66,6 @@
     private int mNumRelroCreationsFinished = 0;
     // Implies that we need to rerun relro creation because we are using an out-of-date package
     private boolean mWebViewPackageDirty = false;
-    // Set to true when the current provider is being replaced
-    private boolean mCurrentProviderBeingReplaced = false;
     private boolean mAnyWebViewInstalled = false;
 
     private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
@@ -78,9 +76,11 @@
     private WebViewProviderInfo[] mCurrentValidWebViewPackages = null;
 
     private BroadcastReceiver mWebViewUpdatedReceiver;
+    private WebViewUtilityInterface mWebViewUtility;
 
     public WebViewUpdateService(Context context) {
         super(context);
+        mWebViewUtility = new WebViewUtilityImpl();
     }
 
     @Override
@@ -92,19 +92,10 @@
                     // the removal of the old package and one representing the addition of the
                     // new package.
                     // In the case where we receive an intent to remove the old version of the
-                    // package that is being replaced we set a flag here and early-out so that we
-                    // don't change provider while replacing the current package (we will instead
-                    // change provider when the new version of the package is being installed).
+                    // package that is being replaced we early-out here so that we don't run the
+                    // update-logic twice.
                     if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)
                         && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
-                        synchronized(WebViewUpdateService.this) {
-                            if (mCurrentWebViewPackage == null) return;
-
-                            String webViewPackage = "package:" + mCurrentWebViewPackage.packageName;
-                            if (webViewPackage.equals(intent.getDataString()))
-                                mCurrentProviderBeingReplaced = true;
-                        }
-
                         return;
                     }
 
@@ -125,7 +116,7 @@
 
                     updateFallbackState(context, intent);
 
-                    for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) {
+                    for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) {
                         String webviewPackage = "package:" + provider.packageName;
 
                         if (webviewPackage.equals(intent.getDataString())) {
@@ -164,11 +155,7 @@
                                 // package that was not the previous provider then we must kill
                                 // packages dependent on the old package ourselves. The framework
                                 // only kills dependents of packages that are being removed.
-                                try {
-                                    ActivityManagerNative.getDefault().killPackageDependents(
-                                        oldProviderName, UserHandle.USER_ALL);
-                                } catch (RemoteException e) {
-                                }
+                                mWebViewUtility.killPackageDependents(oldProviderName);
                             }
                             return;
                         }
@@ -181,7 +168,7 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         // Make sure we only receive intents for WebView packages from our config file.
-        for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) {
+        for (WebViewProviderInfo provider : mWebViewUtility.getWebViewPackages()) {
             filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
         }
         getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
@@ -221,7 +208,7 @@
     void handleNewUser(int userId) {
         if (!isFallbackLogicEnabled()) return;
 
-        WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages();
+        WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages();
         WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
         if (fallbackProvider == null) return;
         boolean existsValidNonFallbackProvider =
@@ -239,7 +226,7 @@
     void updateFallbackState(final Context context, final Intent intent) {
         if (!isFallbackLogicEnabled()) return;
 
-        WebViewProviderInfo[] webviewProviders = WebViewFactory.getWebViewPackages();
+        WebViewProviderInfo[] webviewProviders = mWebViewUtility.getWebViewPackages();
 
         if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)
                     || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) {
@@ -330,10 +317,10 @@
         return false;
     }
 
-    private static boolean isFallbackPackage(String packageName) {
+    private boolean isFallbackPackage(String packageName) {
         if (packageName == null || !isFallbackLogicEnabled()) return false;
 
-        WebViewProviderInfo[] webviewPackages = WebViewFactory.getWebViewPackages();
+        WebViewProviderInfo[] webviewPackages = mWebViewUtility.getWebViewPackages();
         WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages);
         return (fallbackProvider != null
                 && packageName.equals(fallbackProvider.packageName));
@@ -370,13 +357,13 @@
         PackageInfo newPackage = null;
         synchronized(this) {
             oldPackage = mCurrentWebViewPackage;
-            updateUserSetting(newProviderName);
+            mWebViewUtility.updateUserSetting(getContext(), newProviderName);
 
             try {
                 newPackage = findPreferredWebViewPackage();
                 if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) {
                     // If we don't perform the user change, revert the settings change.
-                    updateUserSetting(newPackage.packageName);
+                    mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName);
                     return newPackage.packageName;
                 }
             } catch (WebViewFactory.MissingWebViewPackageException e) {
@@ -389,12 +376,8 @@
             onWebViewProviderChanged(newPackage);
         }
         // Kill apps using the old provider
-        try {
-            if (oldPackage != null) {
-                ActivityManagerNative.getDefault().killPackageDependents(
-                        oldPackage.packageName, UserHandle.USER_ALL);
-            }
-        } catch (RemoteException e) {
+        if (oldPackage != null) {
+            mWebViewUtility.killPackageDependents(oldPackage.packageName);
         }
         return newPackage.packageName;
     }
@@ -406,19 +389,16 @@
     private void onWebViewProviderChanged(PackageInfo newPackage) {
         synchronized(this) {
             mAnyWebViewInstalled = true;
-            // If we have changed provider then the replacement of the old provider is
-            // irrelevant - we can only have chosen a new provider if its package is available.
-            mCurrentProviderBeingReplaced = false;
             if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
                 mCurrentWebViewPackage = newPackage;
-                updateUserSetting(newPackage.packageName);
+                mWebViewUtility.updateUserSetting(getContext(), newPackage.packageName);
 
                 // The relro creations might 'finish' (not start at all) before
                 // WebViewFactory.onWebViewProviderChanged which means we might not know the number
                 // of started creations before they finish.
                 mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
                 mNumRelroCreationsFinished = 0;
-                mNumRelroCreationsStarted = WebViewFactory.onWebViewProviderChanged(newPackage);
+                mNumRelroCreationsStarted = mWebViewUtility.onWebViewProviderChanged(newPackage);
                 // If the relro creations finish before we know the number of started creations we
                 // will have to do any cleanup/notifying here.
                 checkIfRelrosDoneLocked();
@@ -435,7 +415,7 @@
      * */
     private void updateValidWebViewPackages() {
         List<WebViewProviderInfo> webViewProviders  =
-            new ArrayList<WebViewProviderInfo>(Arrays.asList(WebViewFactory.getWebViewPackages()));
+            new ArrayList<WebViewProviderInfo>(Arrays.asList(mWebViewUtility.getWebViewPackages()));
         Iterator<WebViewProviderInfo> it = webViewProviders.iterator();
         // remove non-valid packages
         while(it.hasNext()) {
@@ -449,17 +429,6 @@
         }
     }
 
-    private static String getUserChosenWebViewProvider() {
-        return Settings.Global.getString(AppGlobals.getInitialApplication().getContentResolver(),
-                Settings.Global.WEBVIEW_PROVIDER);
-    }
-
-    private void updateUserSetting(String newProviderName) {
-        Settings.Global.putString(getContext().getContentResolver(),
-                Settings.Global.WEBVIEW_PROVIDER,
-                newProviderName == null ? "" : newProviderName);
-    }
-
     /**
      * Returns either the package info of the WebView provider determined in the following way:
      * If the user has chosen a provider then use that if it is valid,
@@ -470,7 +439,7 @@
     private PackageInfo findPreferredWebViewPackage() {
         WebViewProviderInfo[] providers = mCurrentValidWebViewPackages;
 
-        String userChosenProvider = getUserChosenWebViewProvider();
+        String userChosenProvider = mWebViewUtility.getUserChosenWebViewProvider(getContext());
 
         // If the user has chosen provider, use that
         for (WebViewProviderInfo provider : providers) {
@@ -504,7 +473,6 @@
     private boolean webViewIsReadyLocked() {
         return !mWebViewPackageDirty
             && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
-            && !mCurrentProviderBeingReplaced
             // The current package might be replaced though we haven't received an intent declaring
             // this yet, the following flag makes anyone loading WebView to wait in this case.
             && mAnyWebViewInstalled;
@@ -516,13 +484,8 @@
                 mWebViewPackageDirty = false;
                 // If we have changed provider since we started the relro creation we need to
                 // redo the whole process using the new package instead.
-                // Though, if the current provider package is being replaced we don't want to change
-                // provider here since we will perform the change either when the package is added
-                // again or when we switch to another provider (whichever comes first).
-                if (!mCurrentProviderBeingReplaced) {
-                    PackageInfo newPackage = findPreferredWebViewPackage();
-                    onWebViewProviderChanged(newPackage);
-                }
+                PackageInfo newPackage = findPreferredWebViewPackage();
+                onWebViewProviderChanged(newPackage);
             } else {
                 this.notifyAll();
             }
@@ -597,11 +560,6 @@
                 // Make sure we return the provider that was used to create the relro file
                 webViewPackage = WebViewUpdateService.this.mCurrentWebViewPackage;
                 if (webViewReady) {
-                } else if (mCurrentProviderBeingReplaced) {
-                    // It is important that we check this flag before the one representing WebView
-                    // being installed, otherwise we might think there is no WebView though the
-                    // current one is just being replaced.
-                    webViewStatus = WebViewFactory.LIBLOAD_WEBVIEW_BEING_REPLACED;
                 } else if (!mAnyWebViewInstalled) {
                     webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
                 } else {
@@ -641,6 +599,11 @@
         }
 
         @Override // Binder call
+        public WebViewProviderInfo[] getAllWebViewPackages() {
+            return WebViewUpdateService.this.mWebViewUtility.getWebViewPackages();
+        }
+
+        @Override // Binder call
         public String getCurrentWebViewPackageName() {
             synchronized(WebViewUpdateService.this) {
                 if (WebViewUpdateService.this.mCurrentWebViewPackage == null)
@@ -651,7 +614,7 @@
 
         @Override // Binder call
         public boolean isFallbackPackage(String packageName) {
-            return WebViewUpdateService.isFallbackPackage(packageName);
+            return WebViewUpdateService.this.isFallbackPackage(packageName);
         }
 
         @Override // Binder call
diff --git a/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java b/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java
new file mode 100644
index 0000000..4dbd02d
--- /dev/null
+++ b/services/core/java/com/android/server/webkit/WebViewUtilityImpl.java
@@ -0,0 +1,161 @@
+/*
+ * 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.webkit;
+
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.res.XmlResourceParser;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.AndroidRuntimeException;
+import android.util.Log;
+import android.webkit.WebViewFactory;
+import android.webkit.WebViewFactory.MissingWebViewPackageException;
+import android.webkit.WebViewProviderInfo;
+
+import com.android.internal.util.XmlUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Default implementation for the WebView preparation Utility interface.
+ * @hide
+ */
+public class WebViewUtilityImpl implements WebViewUtilityInterface {
+    private static final String TAG = WebViewUtilityImpl.class.getSimpleName();
+    private static final String TAG_START = "webviewproviders";
+    private static final String TAG_WEBVIEW_PROVIDER = "webviewprovider";
+    private static final String TAG_PACKAGE_NAME = "packageName";
+    private static final String TAG_DESCRIPTION = "description";
+    // Whether or not the provider must be explicitly chosen by the user to be used.
+    private static final String TAG_AVAILABILITY = "availableByDefault";
+    private static final String TAG_SIGNATURE = "signature";
+    private static final String TAG_FALLBACK = "isFallback";
+
+    /**
+     * Returns all packages declared in the framework resources as potential WebView providers.
+     * @hide
+     * */
+    @Override
+    public WebViewProviderInfo[] getWebViewPackages() {
+        int numFallbackPackages = 0;
+        XmlResourceParser parser = null;
+        List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
+        try {
+            parser = AppGlobals.getInitialApplication().getResources().getXml(
+                    com.android.internal.R.xml.config_webview_packages);
+            XmlUtils.beginDocument(parser, TAG_START);
+            while(true) {
+                XmlUtils.nextElement(parser);
+                String element = parser.getName();
+                if (element == null) {
+                    break;
+                }
+                if (element.equals(TAG_WEBVIEW_PROVIDER)) {
+                    String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME);
+                    if (packageName == null) {
+                        throw new MissingWebViewPackageException(
+                                "WebView provider in framework resources missing package name");
+                    }
+                    String description = parser.getAttributeValue(null, TAG_DESCRIPTION);
+                    if (description == null) {
+                        throw new MissingWebViewPackageException(
+                                "WebView provider in framework resources missing description");
+                    }
+                    boolean availableByDefault = "true".equals(
+                            parser.getAttributeValue(null, TAG_AVAILABILITY));
+                    boolean isFallback = "true".equals(
+                            parser.getAttributeValue(null, TAG_FALLBACK));
+                    WebViewProviderInfo currentProvider =
+                            new WebViewProviderInfo(packageName, description, availableByDefault,
+                                isFallback, readSignatures(parser));
+                    if (currentProvider.isFallbackPackage()) {
+                        numFallbackPackages++;
+                        if (numFallbackPackages > 1) {
+                            throw new AndroidRuntimeException(
+                                    "There can be at most one webview fallback package.");
+                        }
+                    }
+                    webViewProviders.add(currentProvider);
+                }
+                else {
+                    Log.e(TAG, "Found an element that is not a webview provider");
+                }
+            }
+        } catch(XmlPullParserException e) {
+            throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
+        } catch(IOException e) {
+            throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
+        } finally {
+            if (parser != null) parser.close();
+        }
+        return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
+    }
+
+    /**
+     * Reads all signatures at the current depth (within the current provider) from the XML parser.
+     */
+    private static String[] readSignatures(XmlResourceParser parser) throws IOException,
+            XmlPullParserException {
+        List<String> signatures = new ArrayList<String>();
+        int outerDepth = parser.getDepth();
+        while(XmlUtils.nextElementWithin(parser, outerDepth)) {
+            if (parser.getName().equals(TAG_SIGNATURE)) {
+                // Parse the value within the signature tag
+                String signature = parser.nextText();
+                signatures.add(signature);
+            } else {
+                Log.e(TAG, "Found an element in a webview provider that is not a signature");
+            }
+        }
+        return signatures.toArray(new String[signatures.size()]);
+    }
+
+    @Override
+    public int onWebViewProviderChanged(PackageInfo packageInfo) {
+        return WebViewFactory.onWebViewProviderChanged(packageInfo);
+    }
+
+    @Override
+    public String getUserChosenWebViewProvider(Context context) {
+        return Settings.Global.getString(context.getContentResolver(),
+                Settings.Global.WEBVIEW_PROVIDER);
+    }
+
+    @Override
+    public void updateUserSetting(Context context, String newProviderName) {
+        Settings.Global.putString(context.getContentResolver(),
+                Settings.Global.WEBVIEW_PROVIDER,
+                newProviderName == null ? "" : newProviderName);
+    }
+
+    @Override
+    public void killPackageDependents(String packageName) {
+        try {
+            ActivityManagerNative.getDefault().killPackageDependents(packageName,
+                    UserHandle.USER_ALL);
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java b/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java
new file mode 100644
index 0000000..1919f40
--- /dev/null
+++ b/services/core/java/com/android/server/webkit/WebViewUtilityInterface.java
@@ -0,0 +1,37 @@
+/*
+ * 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.webkit;
+
+import android.webkit.WebViewProviderInfo;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+
+/**
+ * Utility interface for the WebViewUpdateService.
+ * This interface provides a way to test the WebView preparation mechanism - during normal use this
+ * interface is implemented using calls to the Android framework, but by providing an alternative
+ * implementation we can test the WebView preparation logic without reaching other framework code.
+ * @hide
+ */
+public interface WebViewUtilityInterface {
+    public WebViewProviderInfo[] getWebViewPackages();
+    public int onWebViewProviderChanged(PackageInfo packageInfo);
+
+    public String getUserChosenWebViewProvider(Context context);
+    public void updateUserSetting(Context context, String newProviderName);
+    public void killPackageDependents(String packageName);
+}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index cd771ba..1695615 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -645,15 +645,23 @@
         final boolean fullscreenTask = !inMultiWindowMode();
         final boolean windowsAreFloating = task != null && task.isFloating();
 
-        if (fullscreenTask || (isChildWindow()
-                && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
+        // If the task has temp inset bounds set, we have to make sure all its windows uses
+        // the temp inset frame. Otherwise different display frames get applied to the main
+        // window and the child window, making them misaligned.
+        if (fullscreenTask) {
+            mInsetFrame.setEmpty();
+        } else {
+            task.getTempInsetBounds(mInsetFrame);
+        }
+
+        if (mInsetFrame.isEmpty()  && (fullscreenTask
+                || (isChildWindow() && (mAttrs.privateFlags
+                        & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0))) {
             // We use the parent frame as the containing frame for fullscreen and child windows
             mContainingFrame.set(pf);
             mDisplayFrame.set(df);
-            mInsetFrame.setEmpty();
         } else {
             task.getBounds(mContainingFrame);
-            task.getTempInsetBounds(mInsetFrame);
             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6ce1a64..41eafe7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -711,8 +711,6 @@
 
         // Start a new transaction and apply position & offset.
         final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
-        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
-                "POS " + mTmpSize.left + ", " + mTmpSize.top, false);
         mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
         mLastHidden = true;
 
@@ -1219,17 +1217,17 @@
         }
 
         // We don't apply the stack bounds crop if:
-        // 1. The window is currently animating docked mode or in freeform mode, otherwise the
-        // animating window will be suddenly (docked) or for whole animation (freeform) cut off.
-        // (Note that we still need to apply the crop if the task being docked is non-resizeable,
-        // in which case the task is running in fullscreen size but cropped to stack bounds.)
+        // 1. The window is currently animating in freeform mode, otherwise the animating window
+        // will be suddenly (docked) or for whole animation (freeform) cut off.
         // 2. The window that is being replaced during animation, because it was living in a
         // different stack. If we suddenly crop it to the new stack bounds, it might get cut off.
         // We don't want it to happen, so we let it ignore the stack bounds until it gets removed.
         // The window that will replace it will abide them.
-        if (isAnimating() && (w.mWillReplaceWindow
-                || (w.inDockedWorkspace() && task.isResizeable())
-                || w.inFreeformWorkspace())) {
+        // TODO: identify animations where we don't want to apply docked stack crop to the docked
+        //       task. For example, if the app is going from freeform to docked mode, we may not
+        //       want to apply the crop during the animation, since it will make the app appear
+        //       cropped prematurely.
+        if (isAnimating() && (w.mWillReplaceWindow || w.inFreeformWorkspace())) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index fb07512..be3ad3b 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -119,6 +119,8 @@
             mSurfaceY = top;
 
             try {
+                if (SHOW_TRANSACTIONS) logSurface(
+                        "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
                 mSurfaceControl.setPosition(left, top);
                 mSurfaceControl.setLayerStack(layerStack);
 
@@ -205,6 +207,9 @@
             mSurfaceY = top;
 
             try {
+                if (SHOW_TRANSACTIONS) logSurface(
+                        "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null);
+
                 mSurfaceControl.setPosition(left, top);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Error positioning surface of " + this
@@ -618,6 +623,13 @@
             }
         }
 
+        @Override
+        public void setTransparentRegionHint(Region region) {
+            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setTransparentRegionHint(" + region
+                    + "): OLD: " + this + " . Called by " + Debug.getCallers(3));
+            super.setTransparentRegionHint(region);
+        }
+
         static void dumpAllSurfaces(PrintWriter pw, String header) {
             synchronized (sSurfaces) {
                 final int N = sSurfaces.size();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 16e73fc..5302253 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,13 +21,14 @@
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+
 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;
 import static org.xmlpull.v1.XmlPullParser.TEXT;
 
-import com.google.android.collect.Sets;
-
 import android.Manifest.permission;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accounts.AccountManager;
@@ -50,10 +51,10 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
+import android.app.admin.SecurityLog;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.backup.IBackupManager;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -142,6 +143,7 @@
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 import com.android.server.pm.UserRestrictionsUtils;
+import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -484,9 +486,9 @@
                 new MonitoringCertNotificationTask().execute(intent);
             }
             if (Intent.ACTION_USER_ADDED.equals(action)) {
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
                 removeUserData(userHandle);
             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                 synchronized (DevicePolicyManagerService.this) {
@@ -1273,10 +1275,10 @@
                     final String adminPackage = aa.info.getPackageName();
                     if (packageName == null || packageName.equals(adminPackage)) {
                         if (mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) == null
-                                || mIPackageManager.getReceiverInfo(
-                                    aa.info.getComponent(),
-                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-                                    userHandle) == null) {
+                                || mIPackageManager.getReceiverInfo(aa.info.getComponent(),
+                                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                                        userHandle) == null) {
                             removed = true;
                             policy.mAdminList.remove(i);
                             policy.mAdminMap.remove(aa.info.getComponent());
@@ -1672,7 +1674,7 @@
             if (mOwners.hasDeviceOwner()) {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
                 Slog.i(LOG_TAG, "Set ro.device_owner property to true");
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
                 if (mInjector.securityLogGetLoggingEnabledProperty()) {
                     mSecurityLogMonitor.start();
                 }
@@ -2097,8 +2099,9 @@
         try {
             ai = mIPackageManager.getReceiverInfo(adminName,
                     PackageManager.GET_META_DATA |
-                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
-                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE, userHandle);
+                    PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS |
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE |
+                    PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
         } catch (RemoteException e) {
             // shouldn't happen.
         }
@@ -5612,7 +5615,7 @@
             mOwners.clearDeviceOwner();
             mOwners.writeDeviceOwner();
             updateDeviceOwnerLocked();
-            disableDeviceLoggingIfNotCompliant();
+            disableSecurityLoggingIfNotCompliant();
             // Reactivate backup service.
             long ident = mInjector.binderClearCallingIdentity();
             try {
@@ -7194,11 +7197,13 @@
 
             try {
                 int parentUserId = getProfileParentId(userId);
-                List<ResolveInfo> activitiesToEnable = mIPackageManager.queryIntentActivities(
-                        intent,
-                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
-                        parentUserId).getList();
+                List<ResolveInfo> activitiesToEnable = mIPackageManager
+                        .queryIntentActivities(intent,
+                                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                                parentUserId)
+                        .getList();
 
                 if (VERBOSE_LOG) {
                     Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
@@ -8598,15 +8603,15 @@
         return false;
     }
 
-    private synchronized void disableDeviceLoggingIfNotCompliant() {
+    private synchronized void disableSecurityLoggingIfNotCompliant() {
         if (!isDeviceOwnerManagedSingleUserDevice()) {
             mInjector.securityLogSetLoggingEnabledProperty(false);
-            Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
+            Slog.w(LOG_TAG, "Security logging turned off as it's no longer a single user device.");
         }
     }
 
     @Override
-    public void setDeviceLoggingEnabled(ComponentName admin, boolean enabled) {
+    public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
@@ -8624,7 +8629,7 @@
     }
 
     @Override
-    public boolean getDeviceLoggingEnabled(ComponentName admin) {
+    public boolean isSecurityLoggingEnabled(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         synchronized (this) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -8633,7 +8638,7 @@
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
@@ -8648,7 +8653,7 @@
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrieveDeviceLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index cacc671..79702a8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -17,8 +17,8 @@
 package com.android.server.devicepolicy;
 
 import android.app.admin.DeviceAdminReceiver;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
+import android.app.admin.SecurityLog;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.util.Log;
 import android.util.Slog;
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 19c073c..5975405 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources.Theme;
+import android.os.BaseBundle;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
@@ -35,7 +36,6 @@
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.PowerManager;
-import android.os.RecoverySystem;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -53,6 +53,7 @@
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.os.ZygoteInit;
+import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.am.ActivityManagerService;
@@ -69,10 +70,9 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
-import com.android.internal.widget.ILockSettings;
+import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
 import com.android.server.media.MediaSessionService;
-import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.projection.MediaProjectionManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
@@ -271,6 +271,10 @@
             // explicitly specifying a user.
             Environment.setUserRequired(true);
 
+            // Within the system server, any incoming Bundles should be defused
+            // to avoid throwing BadParcelableException.
+            BaseBundle.setShouldDefuse(true);
+
             // Ensure binder calls into the system always run at foreground priority.
             BinderInternal.disableBackgroundScheduling(true);
 
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index f2f555b..8ab1878 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -443,10 +443,7 @@
             @Nullable List<PrinterId> printerIds) {
         synchronized (mLock) {
             throwIfDestroyedLocked();
-            // No services - nothing to do.
-            if (mActiveServices.isEmpty()) {
-                return;
-            }
+
             // No session - nothing to do.
             if (mPrinterDiscoverySession == null) {
                 return;
@@ -460,10 +457,7 @@
     public void stopPrinterDiscovery(@NonNull IPrinterDiscoveryObserver observer) {
         synchronized (mLock) {
             throwIfDestroyedLocked();
-            // No services - nothing to do.
-            if (mActiveServices.isEmpty()) {
-                return;
-            }
+
             // No session - nothing to do.
             if (mPrinterDiscoverySession == null) {
                 return;
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 69f12eb..34f2e2e 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -161,9 +161,11 @@
                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
                 mIdleHandler = new IdleHandler() {
                     public boolean queueIdle() {
-                        cv.open();
-                        mIdleHandler = null;
-                        return false;  // Remove the handler.
+                        synchronized (queue) {
+                            cv.open();
+                            mIdleHandler = null;
+                            return false;  // Remove the handler.
+                        }
                     }
                 };
                 queue.addIdleHandler(mIdleHandler);
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
new file mode 100644
index 0000000..e440a0d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.am;
+
+import android.content.pm.UserInfo;
+import android.os.Environment;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+
+import com.android.server.am.TaskPersister;
+
+import java.io.File;
+import java.util.Random;
+
+public class TaskPersisterTest extends AndroidTestCase {
+    private static final String TEST_USER_NAME = "AM-Test-User";
+
+    private TaskPersister mTaskPersister;
+    private int testUserId;
+    private UserManager mUserManager;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mUserManager = UserManager.get(getContext());
+        mTaskPersister = new TaskPersister(getContext().getFilesDir());
+        testUserId = createUser(TEST_USER_NAME, 0);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mTaskPersister.unloadUserDataFromMemory(testUserId);
+        removeUser(testUserId);
+    }
+
+    private int getRandomTaskIdForUser(int userId) {
+        int taskId = (int) (Math.random() * UserHandle.PER_USER_RANGE);
+        taskId += UserHandle.PER_USER_RANGE * userId;
+        return taskId;
+    }
+
+    public void testTaskIdsPersistence() {
+        SparseBooleanArray taskIdsOnFile = mTaskPersister.loadPersistedTaskIdsForUser(testUserId);
+        for (int i = 0; i < 100; i++) {
+            taskIdsOnFile.put(getRandomTaskIdForUser(testUserId), true);
+        }
+        mTaskPersister.maybeWritePersistedTaskIdsForUser(taskIdsOnFile, testUserId);
+        SparseBooleanArray newTaskIdsOnFile = mTaskPersister
+                .loadPersistedTaskIdsForUser(testUserId);
+        assertTrue("TaskIds written differ from TaskIds read back from file",
+                taskIdsOnFile.equals(newTaskIdsOnFile));
+    }
+
+    private int createUser(String name, int flags) {
+        UserInfo user = mUserManager.createUser(name, flags);
+        if (user == null) {
+            fail("Error while creating the test user: " + TEST_USER_NAME);
+        }
+        return user.id;
+    }
+
+    private void removeUser(int userId) {
+        if (!mUserManager.removeUser(userId)) {
+            fail("Error while removing the test user: " + TEST_USER_NAME);
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index 6bcaf4d..ad86fd0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -57,6 +57,7 @@
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
+import android.util.SparseArray;
 
 import com.android.frameworks.servicestests.R;
 import com.android.internal.util.Preconditions;
@@ -165,8 +166,8 @@
     private final class ShortcutServiceTestable extends ShortcutService {
         final ServiceContext mContext;
 
-        public ShortcutServiceTestable(ServiceContext context) {
-            super(context);
+        public ShortcutServiceTestable(ServiceContext context, Looper looper) {
+            super(context, looper);
             mContext = context;
         }
 
@@ -247,9 +248,20 @@
         @Override
         void postToHandler(Runnable r) {
             final long token = mContext.injectClearCallingIdentity();
-            r.run();
+            super.postToHandler(r);
+            try {
+                runTestOnUiThread(() -> {});
+            } catch (Throwable e) {
+                fail("runTestOnUiThread failed: " + e);
+            }
             mContext.injectRestoreCallingIdentity(token);
         }
+
+        @Override
+        void wtf(String message, Exception e) {
+            // During tests, WTF is fatal.
+            fail(message + "  exception: " + e);
+        }
     }
 
     /** ShortcutManager with injection override methods. */
@@ -295,7 +307,7 @@
         }
 
         @Override
-        void postToPackageMonitor(Runnable r) {
+        void postToPackageMonitorHandler(Runnable r) {
             final long token = mContext.injectClearCallingIdentity();
             r.run();
             mContext.injectRestoreCallingIdentity(token);
@@ -361,7 +373,7 @@
     private static final int USER_10 = 10;
     private static final int USER_11 = 11;
 
-    private static final long START_TIME = 1234560000000L;
+    private static final long START_TIME = 1440000000101L;
 
     private static final long INTERVAL = 10000;
 
@@ -417,7 +429,7 @@
         LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
 
         // Instantiate targets.
-        mService = new ShortcutServiceTestable(mServiceContext);
+        mService = new ShortcutServiceTestable(mServiceContext, Looper.getMainLooper());
         mManager = new ShortcutManagerTestable(mClientContext, mService);
 
         mInternal = LocalServices.getService(ShortcutServiceInternal.class);
@@ -502,6 +514,7 @@
      * For debugging, dump the main state file on logcat.
      */
     private void dumpBaseStateFile() {
+        mService.saveDirtyInfo();
         dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
                 + "/system/" + ShortcutService.FILENAME_BASE_STATE);
     }
@@ -510,6 +523,7 @@
      * For debugging, dump per-user state file on logcat.
      */
     private void dumpUserFile(int userId) {
+        mService.saveDirtyInfo();
         dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
                 + "/user-" + userId
                 + "/" + ShortcutService.FILENAME_USER_PACKAGES);
@@ -883,6 +897,8 @@
 
         dumpBaseStateFile();
 
+        mService.saveDirtyInfo();
+
         // Restore.
         initService();
 
@@ -1118,51 +1134,102 @@
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(1, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         // Reached the max
 
         mInjectedCurrentTimeLillis++;
         assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         // Still throttled
         mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
         assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         // Now it should work.
         mInjectedCurrentTimeLillis++;
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1))); // fail
         assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(1, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
         assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         // 4 days later...
         mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
 
-        // Make sure getRemainingCallCount() itself gets reset withou calling setDynamicShortcuts().
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(1, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
+
+        // Make sure getRemainingCallCount() itself gets reset without calling setDynamicShortcuts().
         mInjectedCurrentTimeLillis = START_TIME + 8 * INTERVAL;
         assertEquals(3, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
+
+        mInjectedCurrentTimeLillis++;
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
+    }
+
+    public void testThrottling_rewind() {
+        final ShortcutInfo si1 = makeShortcut("shortcut1");
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+        mInjectedCurrentTimeLillis = 12345; // Clock reset!
+
+        // Since the clock looks invalid, the counter shouldn't have reset.
+        assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+        // Forward again.  Still haven't reset yet.
+        mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
+        assertEquals(2, mManager.getRemainingCallCount());
+        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+
+        // Now rewind -- this will reset the counters.
+        mInjectedCurrentTimeLillis = START_TIME - 100000;
+        assertEquals(3, mManager.getRemainingCallCount());
+
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertEquals(2, mManager.getRemainingCallCount());
+
+        // Forward again, should be reset now.
+        mInjectedCurrentTimeLillis += INTERVAL;
+        assertEquals(3, mManager.getRemainingCallCount());
     }
 
     public void testThrottling_perPackage() {
@@ -1284,6 +1351,7 @@
                 "none");
 
         // Re-initialize and load from the files.
+        mService.saveDirtyInfo();
         initService();
 
         // Load from launcher.
@@ -1752,68 +1820,321 @@
 
     public void testPinShortcutAndGetPinnedShortcuts() {
         // Create some shortcuts.
-        setCaller(CALLING_PACKAGE_1);
-        final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
-        final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
+            final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+        });
 
-        setCaller(CALLING_PACKAGE_2);
-        final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
-        final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
-        final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
+            final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
+            final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+        });
 
-        setCaller(CALLING_PACKAGE_3);
-        final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2)));
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2)));
+        });
 
         // Pin some.
-        setCaller(LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    Arrays.asList("s2", "s3"), getCallingUser());
 
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                Arrays.asList("s2", "s3"), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    Arrays.asList("s3", "s4", "s5"), getCallingUser());
 
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                Arrays.asList("s3", "s4", "s5"), getCallingUser());
-
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
-                Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
+                    Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
+        });
 
         // Delete some.
-        setCaller(CALLING_PACKAGE_1);
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
-        mManager.deleteDynamicShortcut("s2");
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+            mManager.deleteDynamicShortcut("s2");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+        });
 
-        setCaller(CALLING_PACKAGE_2);
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
-        mManager.deleteDynamicShortcut("s3");
-        assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+            mManager.deleteDynamicShortcut("s3");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+        });
 
-        setCaller(CALLING_PACKAGE_3);
-        assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
-        mManager.deleteDynamicShortcut("s2");
-        assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+            mManager.deleteDynamicShortcut("s2");
+            assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+        });
 
         // Get pinned shortcuts from launcher
-        setCaller(LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s2");
 
-        // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
-        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
-                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
-                "s2");
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3", "s4");
 
-        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
-                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
-                "s3", "s4");
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                    /* none */);
+        });
+    }
 
-        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
-                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
-                /* none */);
+    public void testPinShortcutAndGetPinnedShortcuts_multi() {
+        // Create some shortcuts.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        dumpsysOnLogcat();
+
+        // Pin some.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    Arrays.asList("s3", "s4"), getCallingUser());
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    Arrays.asList("s1", "s2", "s4"), getCallingUser());
+        });
+
+        dumpsysOnLogcat();
+
+        // Delete some.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+            mManager.deleteDynamicShortcut("s3");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+        });
+
+        dumpsysOnLogcat();
+
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
+            mManager.deleteDynamicShortcut("s1");
+            mManager.deleteDynamicShortcut("s3");
+            assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
+        });
+
+        dumpsysOnLogcat();
+
+        // Get pinned shortcuts from launcher
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2");
+
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2", "s3");
+
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+        });
+
+        dumpsysOnLogcat();
+
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            // Launcher2 still has no pinned ones.
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                    /* none */);
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
+                    /* none */);
+
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s2");
+
+            // Now pin some.
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    Arrays.asList("s1", "s2"), getCallingUser());
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    Arrays.asList("s1", "s2"), getCallingUser());
+
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+
+            // S1 was not visible to it, so shouldn't be pinned.
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s2");
+        });
+
+        // Re-initialize and load from the files.
+        mService.saveDirtyInfo();
+        initService();
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2");
+        });
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s1", "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
+                    "s2");
+        });
+
+        // Delete all dynamic.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            mManager.deleteAllDynamicShortcuts();
+
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            mManager.deleteAllDynamicShortcuts();
+
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2", "s1");
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2");
+
+            // from all packages.
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, null,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s2", "s3");
+
+            // Update pined.  Note s2 and s3 are actually available, but not visible to this
+            // launcher, so still can't be pinned.
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+                    getCallingUser());
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+        });
+        // Re-publish s1.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
+        });
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s3");
+
+            // Now "s1" is visible, so can be pinned.
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+                    getCallingUser());
+
+            assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
+                    "s1", "s3");
+        });
+
+        // Now clear pinned shortcuts.  First, from launcher 1.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2");
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2");
+        });
+
+        // Clear all pins from launcher 2.
+        runWithCaller(LAUNCHER_2, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+            assertEquals(0,
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertEquals(0, mManager.getDynamicShortcuts().size());
+            assertEquals(0, mManager.getPinnedShortcuts().size());
+        });
     }
 
     public void testCreateShortcutIntent() {
@@ -1880,8 +2201,11 @@
     }
 
     public void testLauncherCallback() throws Throwable {
-        LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
 
+        // TODO Add "multi" version -- run the test with two launchers and make sure the callback
+        // argument only contains the ones that are actually visible to each launcher.
+
+        LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
 
         // Set listeners
 
@@ -2008,6 +2332,7 @@
         dumpUserFile(0);
 
         // Restore.
+        mService.saveDirtyInfo();
         initService();
 
         assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -2104,6 +2429,7 @@
                 mService, new ComponentName("pkg1", "class"));
 
         // Restore.
+        mService.saveDirtyInfo();
         initService();
 
         // Before the load, the map should be empty.
@@ -2152,7 +2478,7 @@
         assertNull(mService.getShortcutsForTest().get(USER_10).getLauncherComponent());
 
         // Try stopping the user
-        mService.onCleanupUserInner(USER_10);
+        mService.onCleanupUserLocked(USER_10);
 
         // Now it's unloaded.
         assertEquals(1, mService.getShortcutsForTest().size());
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 2ab0525..a965342 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -44,6 +44,7 @@
     public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
 
     private static MessageDigest sMessageDigest;
+    private static final Object sMessageDigestLock = new Object();
 
     private Log() {}
 
@@ -57,7 +58,9 @@
                 } catch (NoSuchAlgorithmException e) {
                     md = null;
                 }
-                sMessageDigest = md;
+                synchronized (sMessageDigestLock) {
+                    sMessageDigest = md;
+                }
                 return null;
             }
         }.execute();
@@ -187,13 +190,15 @@
     }
 
     private static String secureHash(byte[] input) {
-        if (sMessageDigest != null) {
-            sMessageDigest.reset();
-            sMessageDigest.update(input);
-            byte[] result = sMessageDigest.digest();
-            return encodeHex(result);
-        } else {
-            return "Uninitialized SHA1";
+        synchronized (sMessageDigestLock) {
+            if (sMessageDigest != null) {
+                sMessageDigest.reset();
+                sMessageDigest.update(input);
+                byte[] result = sMessageDigest.digest();
+                return encodeHex(result);
+            } else {
+                return "Uninitialized SHA1";
+            }
         }
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ea437d0..86518b5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -444,6 +444,11 @@
     public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
 
     /**
+     * Flag specifying whether ICCID is showed in SIM Status screen, default to false.
+     */
+    public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
+
+    /**
      * Flag specifying whether an additional (client initiated) intent needs to be sent on System
      * update
      */
@@ -680,6 +685,7 @@
         sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
         sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
         sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
+        sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 84cffe1..b739ead 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -151,7 +151,7 @@
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
         throw new UnsupportedOperationException();
     }
 
@@ -258,7 +258,7 @@
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
         throw new UnsupportedOperationException();
     }
 
@@ -726,26 +726,26 @@
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
+    public Context createDeviceProtectedStorageContext() {
         throw new UnsupportedOperationException();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public Context createCredentialEncryptedStorageContext() {
+    public Context createCredentialProtectedStorageContext() {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
+    public boolean isDeviceProtectedStorage() {
         throw new UnsupportedOperationException();
     }
 
     /** {@hide} */
     @SystemApi
     @Override
-    public boolean isCredentialEncryptedStorage() {
+    public boolean isCredentialProtectedStorage() {
         throw new UnsupportedOperationException();
     }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index e851c8d..91e891f 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -758,6 +758,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void addPreferredActivity(IntentFilter filter,
             int match, ComponentName[] set, ComponentName activity) {
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml
new file mode 100644
index 0000000..d5d86d8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml
@@ -0,0 +1,33 @@
+<?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.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml
new file mode 100644
index 0000000..9754e4b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml
@@ -0,0 +1,33 @@
+<?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.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index 495d620..5856f49 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -35,6 +35,8 @@
 public class VectorDrawablePerformance extends Activity {
     private static final String LOGCAT = "VectorDrawable1";
     protected int[] icon = {
+            R.drawable.vector_icon_filltype_nonzero,
+            R.drawable.vector_icon_filltype_evenodd,
             R.drawable.vector_icon_gradient_1,
             R.drawable.vector_icon_gradient_2,
             R.drawable.vector_icon_gradient_3,
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index fb2213c..c16de7b 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -67,6 +67,20 @@
     sys.exit('None of characters in %s were found in %s' % (chars, font))
 
 
+def assert_font_supports_all_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        assert char in best_cmap, (
+            'U+%04X was not found in %s' % (char, font))
+
+
+def assert_font_supports_none_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        assert char not in best_cmap, (
+            'U+%04X was found in %s' % (char, font))
+
+
 def check_hyphens(hyphens_dir):
     # Find all the scripts that need automatic hyphenation
     scripts = set()
@@ -141,6 +155,93 @@
                 _script_to_font_map[script].add((font_file, index))
 
 
+def check_emoji_availability():
+    emoji_fonts = [font[5] for font in _fallback_chain if 'Zsye' in font[1]]
+    emoji_chars = _emoji_properties['Emoji']
+    for emoji_font in emoji_fonts:
+        assert_font_supports_all_of_chars(emoji_font, emoji_chars)
+
+
+def check_emoji_defaults():
+    default_emoji_chars = _emoji_properties['Emoji_Presentation']
+    missing_text_chars = _emoji_properties['Emoji'] - default_emoji_chars
+    emoji_font_seen = False
+    for name, scripts, variant, weight, style, font in _fallback_chain:
+        if 'Zsye' in scripts:
+            emoji_font_seen = True
+            # No need to check the emoji font
+            continue
+        # For later fonts, we only check them if they have a script
+        # defined, since the defined script may get them to a higher
+        # score even if they appear after the emoji font.
+        if emoji_font_seen and not scripts:
+            continue
+
+        # Check default emoji-style characters
+        assert_font_supports_none_of_chars(font, sorted(default_emoji_chars))
+
+        # Mark default text-style characters appearing in fonts above the emoji
+        # font as seen
+        if not emoji_font_seen:
+            missing_text_chars -= set(get_best_cmap(font))
+
+    # Noto does not have monochrome symbols for Unicode 7.0 wingdings and
+    # webdings
+    missing_text_chars -= _chars_by_age['7.0']
+    # TODO: Remove these after b/26113320 is fixed
+    missing_text_chars -= {
+        0x263A, # WHITE SMILING FACE
+        0x270C, # VICTORY HAND
+        0x2744, # SNOWFLAKE
+        0x2764, # HEAVY BLACK HEART
+    }
+    assert missing_text_chars == set(), (
+        'Text style version of some emoji characters are missing.')
+
+
+# Setting reverse to true returns a dictionary that maps the values to sets of
+# characters, useful for some binary properties. Otherwise, we get a
+# dictionary that maps characters to the property values, assuming there's only
+# one property in the file.
+def parse_unicode_datafile(file_path, reverse=False):
+    if reverse:
+        output_dict = collections.defaultdict(set)
+    else:
+        output_dict = {}
+    with open(file_path) as datafile:
+        for line in datafile:
+            if '#' in line:
+                line = line[:line.index('#')]
+            line = line.strip()
+            if not line:
+                continue
+            char_range, prop = line.split(';')
+            char_range = char_range.strip()
+            prop = prop.strip()
+            if '..' in char_range:
+                char_start, char_end = char_range.split('..')
+            else:
+                char_start = char_end = char_range
+            char_start = int(char_start, 16)
+            char_end = int(char_end, 16)
+            char_range = xrange(char_start, char_end+1)
+            if reverse:
+                output_dict[prop].update(char_range)
+            else:
+                for char in char_range:
+                    assert char not in output_dict
+                    output_dict[char] = prop
+    return output_dict
+
+
+def parse_ucd(ucd_path):
+    global _emoji_properties, _chars_by_age
+    _emoji_properties = parse_unicode_datafile(
+        path.join(ucd_path, 'emoji-data.txt'), reverse=True)
+    _chars_by_age = parse_unicode_datafile(
+        path.join(ucd_path, 'DerivedAge.txt'), reverse=True)
+
+
 def main():
     target_out = sys.argv[1]
     global _fonts_dir
@@ -152,6 +253,11 @@
     hyphens_dir = path.join(target_out, 'usr', 'hyphen-data')
     check_hyphens(hyphens_dir)
 
+    ucd_path = sys.argv[2]
+    parse_ucd(ucd_path)
+    check_emoji_availability()
+    check_emoji_defaults()
+
 
 if __name__ == '__main__':
     main()
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index c7ae6fc..b3f1ee1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1258,7 +1258,7 @@
     }
 
     @Override
-    public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+    public boolean moveDatabaseFrom(Context sourceContext, String name) {
         // pass
         return false;
     }
@@ -1451,7 +1451,7 @@
     }
 
     @Override
-    public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+    public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
         // pass
         return false;
     }
@@ -1838,24 +1838,24 @@
     }
 
     @Override
-    public Context createDeviceEncryptedStorageContext() {
+    public Context createDeviceProtectedStorageContext() {
         // pass
         return null;
     }
 
     @Override
-    public Context createCredentialEncryptedStorageContext() {
+    public Context createCredentialProtectedStorageContext() {
         // pass
         return null;
     }
 
     @Override
-    public boolean isDeviceEncryptedStorage() {
+    public boolean isDeviceProtectedStorage() {
         return false;
     }
 
     @Override
-    public boolean isCredentialEncryptedStorage() {
+    public boolean isCredentialProtectedStorage() {
         return false;
     }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 4039cdf..42c0ae0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -715,6 +715,10 @@
     }
 
     @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+    }
+
+    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle userHandle) {
         return false;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index e9b7819..9f73d79 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -86,6 +86,11 @@
     }
 
     @Override
+    public void rebootSafeMode(boolean confirm, boolean wait) {
+        // pass for now.
+    }
+
+    @Override
     public void shutdown(boolean confirm, String reason, boolean wait) {
         // pass for now.
     }